# Prevent a gutter icon from becoming a Zombie

**URL:** https://platform.jetbrains.com/t/prevent-a-gutter-icon-from-becoming-a-zombie/3672
**Category:** IntelliJ Platform
**Created:** [February 9, 2026, 5:58pm UTC](https://platform.jetbrains.com/t/prevent-a-gutter-icon-from-becoming-a-zombie/3672 "2026-02-09T17:58:49Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![abrooksv](https://sea1.discourse-cdn.com/flex001/user_avatar/platform.jetbrains.com/abrooksv/32/924_2.png) [@abrooksv](https://platform.jetbrains.com/u/abrooksv)
#### Post date: [February 9, 2026, 5:58pm UTC](https://platform.jetbrains.com/t/prevent-a-gutter-icon-from-becoming-a-zombie/3672/1 "2026-02-09T17:58:49Z")

</div>

I have an ExternalToolPass that creates gutter icons based on loading remote data from an API. When editors are destroyed and revived by the Zombie/Necromancer system, the gutter icons flash in and you can’t interact with them and they then disappear again since the data is not present in the local caches.

Is there a way I am overlooking to tell the HighlightingNecromancer to skip those gutter icons? Do I need to make a custom HighlightSeverity with a low level (\<10) level, what are the ramifications of doing that?

> <https://github.com/JetBrains/intellij-community/blob/1e05f4447723efe125034ffad6a3764387893163/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HighlightingNecromancer.kt#L173-L190>

---

<div class="post-metadata">

### Author: ![yuriy.artamonov](https://sea1.discourse-cdn.com/flex001/user_avatar/platform.jetbrains.com/yuriy.artamonov/32/48_2.png) [@yuriy.artamonov](https://platform.jetbrains.com/u/yuriy.artamonov)
#### Post date: [March 25, 2026, 8:30am UTC](https://platform.jetbrains.com/t/prevent-a-gutter-icon-from-becoming-a-zombie/3672/2 "2026-03-25T08:30:17Z")

</div>

Hi!

> HighlightSeverity with a low level (\<10) level

This might work and will not even break. Although it would be great to express your need in a more concrete issue so we can introduce a proper API

---

<div class="post-metadata">

### Author: ![abrooksv](https://sea1.discourse-cdn.com/flex001/user_avatar/platform.jetbrains.com/abrooksv/32/924_2.png) [@abrooksv](https://platform.jetbrains.com/u/abrooksv)
#### Post date: [March 25, 2026, 5:13pm UTC](https://platform.jetbrains.com/t/prevent-a-gutter-icon-from-becoming-a-zombie/3672/3 "2026-03-25T17:13:59Z")

</div>

The issue comes from we need to build gutters and inlays from async operations so the control flow ends up being:

1. IDE loads up the zombies, adds the placeholders that have the same L&F of the gutters when closed. They can’t be interacted with since the AnActions can’t be rebuilt so can’t be interacted with
2. DCA runs the passes to do the real highlighting
3. We extract any PSI related data we need to make the async calls, but since cache is cold we return no inlays and no annotations to add
4. The zombies are removed and so gutters and inlays disappear
5. Eventually our async APIs calculate the data and tell the DCA to restart
6. Inlays and gutter icons get added in the new pass when the extracted data hits the warmed cache

This leads to the flashing I was referring to.

Passes like ExternalToolPass work well for us since it is designed to handle slower calculations, but no such thing exists for Inlay passes.

---

<div class="post-metadata">

### Author: ![yuriy.artamonov](https://sea1.discourse-cdn.com/flex001/user_avatar/platform.jetbrains.com/yuriy.artamonov/32/48_2.png) [@yuriy.artamonov](https://platform.jetbrains.com/u/yuriy.artamonov)
#### Post date: [March 25, 2026, 5:27pm UTC](https://platform.jetbrains.com/t/prevent-a-gutter-icon-from-becoming-a-zombie/3672/4 "2026-03-25T17:27:04Z")

</div>

We usually achieve that by loading everything in bulk on background and then once all info is available we do one restart of `DaemonCodeAnalyzer` to show all inlays / gutters

---

<div class="post-metadata">

### Author: ![abrooksv](https://sea1.discourse-cdn.com/flex001/user_avatar/platform.jetbrains.com/abrooksv/32/924_2.png) [@abrooksv](https://platform.jetbrains.com/u/abrooksv)
#### Post date: [March 25, 2026, 5:34pm UTC](https://platform.jetbrains.com/t/prevent-a-gutter-icon-from-becoming-a-zombie/3672/5 "2026-03-25T17:34:11Z")

</div>

Yea, that’s our approach today, but per-file restart since the API calls are related to PSI data in the file (such as extracting all the Logger.info()) calls in the file.

(Sometimes this is not straightforward, like the DeclaritiveInlaysHintPass is cached and the method to clear the cache is marked as [internal](https://github.com/JetBrains/intellij-community/blob/c8cba92f81ec5a85efacae0e407995955e12ac70/platform/lang-impl/src/com/intellij/codeInsight/hints/declarative/impl/DeclarativeInlayHintsPassFactory.kt#L62-L71), there is a public method that looks like it can be [used](https://github.com/JetBrains/intellij-community/blob/c8cba92f81ec5a85efacae0e407995955e12ac70/platform/lang-impl/src/com/intellij/codeInsight/hints/declarative/impl/DeclarativeInlayHintsPassFactory.kt#L53-L56). But non-declaritivie hints has the same method [deprecated](https://github.com/JetBrains/intellij-community/blob/c8cba92f81ec5a85efacae0e407995955e12ac70/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/InlayHintsPassFactoryInternal.kt#L72-L82), the API not being mirrored and consistent is a bit surprising)

We could experiment with writing our own passes (at least for inlays) that operate similar to ExternalToolPass, but we haven’t done that yet. It wouldn’t solve the Zombie stuff per-se but may make our code more straightforward and easier to reason about.
