{"record":{"id":"cf97f916a765cb31","repo":"apache/druid","slug":"no-such-sink-s","errorCode":null,"errorMessage":"No such sink: %s","messagePattern":"No such sink: (.+?)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"server/src/main/java/org/apache/druid/segment/realtime/appenderator/StreamAppenderator.java","lineNumber":472,"sourceCode":"        isPersistRequired = true;\n      }\n    }\n    return new AppenderatorAddResult(identifier, sink.getNumRows(), isPersistRequired);\n  }\n\n  @Override\n  public List<SegmentIdWithShardSpec> getSegments()\n  {\n    return ImmutableList.copyOf(sinks.keySet());\n  }\n\n  @Override\n  public int getRowCount(final SegmentIdWithShardSpec identifier)\n  {\n    final Sink sink = sinks.get(identifier);\n\n    if (sink == null) {\n      throw new ISE(\"No such sink: %s\", identifier);\n    } else {\n      return sink.getNumRows();\n    }\n  }\n\n  @Override\n  public int getTotalRowCount()\n  {\n    return totalRows.get();\n  }\n\n  @VisibleForTesting\n  int getRowsInMemory()\n  {\n    return rowsCurrentlyInMemory.get();\n  }\n\n  @VisibleForTesting","sourceCodeStart":454,"sourceCodeEnd":490,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/server/src/main/java/org/apache/druid/segment/realtime/appenderator/StreamAppenderator.java#L454-L490","documentation":"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.","triggerScenarios":"Calling getRowCount with a SegmentIdWithShardSpec that was never added, or after the sink was dropped/handed off (removed from the sinks map).","commonSituations":"Custom ingestion frameworks querying row counts after segment handoff; identifier serialization/deserialization mismatches changing shard spec hash codes.","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."],"exampleFix":"// before\nint rows = appenderator.getRowCount(identifier); // may not exist\n\n// after\nif (appenderator.getSinks().containsKey(identifier)) {\n  int rows = appenderator.getRowCount(identifier);\n}","handlingStrategy":"validation","validationCode":"if (!appenderator.getSinks().containsKey(identifier)) { return 0; } // or skip metric reporting","typeGuard":null,"tryCatchPattern":"try { return appenderator.getRowCount(id) } catch (IllegalStateException e) { if (e.getMessage().startsWith(\"No such sink\")) { return -1; } throw e; }","preventionTips":["Only query row counts for identifiers currently returned by getSinks()","Stop tracking identifiers after handoff","Centralize identifier lifecycle management"],"tags":["druid","ingestion","resource-not-found"],"backgroundTag":"entity-not-found","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}