apache/druid · error · IllegalStateException
No such sink
Error message
No such sink: %s
What it means
StreamAppenderator.getRowCount returns the in-memory row count of the sink for the given segment identifier and throws ISE if no such sink exists in the appenderator's sinks map. It is a programmer/API misuse signal: asking for metrics of a segment this appenderator never managed.
Solutions
- Track identifiers returned by add/append and only query row counts for live segments.
- Handle handoff: drop the identifier after push/persist indicates the sink is gone.
- Use getMetrics() or the appenderator's metrics emitter instead of direct sink lookups when unsure.
Example fix
// before
int rows = appenderator.getRowCount(identifier); // may not exist
// after
if (appenderator.getSinks().containsKey(identifier)) {
int rows = appenderator.getRowCount(identifier);
} Defensive patterns
Strategy: validation
Validate before calling
if (!appenderator.getSinks().containsKey(identifier)) { return 0; } // or skip metric reporting Try / catch
try { return appenderator.getRowCount(id) } catch (IllegalStateException e) { if (e.getMessage().startsWith("No such sink")) { return -1; } throw e; } Prevention
- Only query row counts for identifiers currently returned by getSinks()
- Stop tracking identifiers after handoff
- Centralize identifier lifecycle management
When it happens
Trigger: Calling getRowCount with a SegmentIdWithShardSpec that was never added, or after the sink was dropped/handed off (removed from the sinks map).
Common situations: Custom ingestion frameworks querying row counts after segment handoff; identifier serialization/deserialization mismatches changing shard spec hash codes.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
- Attempt to add row to swapped-out sink for segment
- Bloom filter aggregators are query-time only
- Can't find pushedSegments for segment
- Can't find segmentsForSequence for sequence
- Cannot simultaneously replace and append to existing…
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/cf97f916a765cb31.
Report an issue: GitHub.
Appendix: source
Thrown at server/src/main/java/org/apache/druid/segment/realtime/appenderator/StreamAppenderator.java:472
isPersistRequired = true;
}
}
return new AppenderatorAddResult(identifier, sink.getNumRows(), isPersistRequired);
}
@Override
public List<SegmentIdWithShardSpec> getSegments()
{
return ImmutableList.copyOf(sinks.keySet());
}
@Override
public int getRowCount(final SegmentIdWithShardSpec identifier)
{
final Sink sink = sinks.get(identifier);
if (sink == null) {
throw new ISE("No such sink: %s", identifier);
} else {
return sink.getNumRows();
}
}
@Override
public int getTotalRowCount()
{
return totalRows.get();
}
@VisibleForTesting
int getRowsInMemory()
{
return rowsCurrentlyInMemory.get();
}
@VisibleForTestingView on GitHub (pinned to 9b90983fd2)