apache/druid · error · IllegalStateException

Can't add [%d, %s] to non-empty SingleEntryShort2ObjectSorte

Error message

Can't add [%d, %s] to non-empty SingleEntryShort2ObjectSortedMap[%d, %s]

What it means

OvershadowableManager's internal SingleEntryShort2ObjectSortedMap can only hold one key/value pair. When a second entry with a different short key is added, it throws this IllegalStateException because the map has no capacity to grow — the caller must first convert the single-entry map to a full sorted map. It is an internal invariant violation indicating the bucket promotion logic should have run before the insert.

Source

Thrown at processing/src/main/java/org/apache/druid/timeline/partition/OvershadowableManager.java:1268

          return key < 0 ? 0 : 1;
        }
      };
    }

    @Override
    public V put(final short key, final V value)
    {
      if (isEmpty()) {
        this.key = key;
        this.val = value;
        return null;
      } else {
        if (this.key == key) {
          final V existing = this.val;
          this.val = value;
          return existing;
        } else {
          throw new ISE(
              "Can't add [%d, %s] to non-empty SingleEntryShort2ObjectSortedMap[%d, %s]",
              key,
              value,
              this.key,
              this.val
          );
        }
      }
    }

    @Override
    public V get(short key)
    {
      return this.key == key ? val : null;
    }

    @Override
    public V remove(final short key)

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Ensure all adds to OvershadowableManager go through its synchronized/public API so the single-entry map is promoted to a multi-entry map when a second distinct key arrives
  2. Check for concurrent access to the same OvershadowableManager and add external synchronization if multiple threads can add partitions
  3. If constructing the map directly in tests, use a multi-entry Short2ObjectSortedMap implementation instead of the single-entry one
  4. Upgrade Druid — interleavings that produced this were fixed in later timeline-partition refactorings

Example fix

// before
map.add((short) 5, chunkA);
map.add((short) 7, chunkB); // throws: single-entry map
// after
OvershadowableManager<PartitionChunk<String>> mgr = OvershadowableManager.create(0);
mgr.add(Partitions.makeChunk(chunkA));
mgr.add(Partitions.makeChunk(chunkB)); // manager promotes internally
Defensive patterns

Strategy: try-catch

Validate before calling

if (manager.canAddHolder() /* or check existing partitionIds first */) {
  // safe to add
}

Try / catch

try {
  manager.add(chunk);
} catch (IllegalStateException e) {
  if (e.getMessage() != null && e.getMessage().startsWith("Can't add")) {
    // rebuild manager from snapshot / retry under lock
  } else throw e;
}

Prevention

When it happens

Trigger: Calling OvershadowableManager.add with a partition whose partitionId differs from the one already held in the single-entry map, when the map was not promoted to a MultiEntry map first (e.g. add called in an unexpected interleaving without going through the promote logic).

Common situations: Concurrency bugs where two threads add partitions to the same OvershadowableManager simultaneously; custom code or tests constructing SingleEntryShort2ObjectSortedMap directly and inserting two distinct keys; version-specific regressions in segment publishing/overshadow tracking.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/5349ba87790abc76. Report an issue: GitHub.