{"record":{"id":"bf05f69d8bfb9793","repo":"apache/druid","slug":"pos-d-out-of-range-d-d-bf05f6","errorCode":null,"errorMessage":"pos %d out of range [%d, %d]","messagePattern":"pos (.+?) out of range \\[(.+?), (.+?)\\]","errorType":"exception","errorClass":"org.apache.druid.java.util.common.IAE","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/segment/writeout/LegacyFileWriteOutBytes.java","lineNumber":141,"sourceCode":"\n  @Override\n  public void writeTo(WritableByteChannel channel) throws IOException\n  {\n    flush();\n    ch.position(0);\n    try {\n      ByteStreams.copy(ch, channel);\n    }\n    finally {\n      ch.position(ch.size());\n    }\n  }\n\n  @Override\n  public void readFully(long pos, ByteBuffer buffer) throws IOException\n  {\n    if (pos < 0 || pos > writeOutBytes) {\n      throw new IAE(\"pos %d out of range [%d, %d]\", pos, 0, writeOutBytes);\n    }\n    flush();\n    ch.read(buffer, pos);\n    if (buffer.remaining() > 0) {\n      throw new BufferUnderflowException();\n    }\n  }\n\n  @Override\n  public InputStream asInputStream() throws IOException\n  {\n    flush();\n    return new FileInputStream(file);\n  }\n\n  @Override\n  public boolean isOpen()\n  {","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/segment/writeout/LegacyFileWriteOutBytes.java#L123-L159","documentation":"LegacyFileWriteOutBytes.readFully checks pos against [0, writeOutBytes] (bytes written so far) and throws IAE when out of range. It prevents reading outside the data actually persisted by this writer.","triggerScenarios":"readFully(pos, buffer) with negative pos or pos beyond the bytes written: stale offsets from an older build of the same segment, mismatched size assumptions, or overflow.","commonSituations":"Reading legacy segments with offsets produced by a different writer; resuming a task against partially rewritten files; concurrent appends changing writeOutBytes between planning and reading.","solutions":["Recompute offsets against the current writer size before reading; do not trust persisted offsets without validation.","Call flush()/writeTo first to ensure logical and on-disk state agree.","Validate segment files (checksum/size metadata) and rebuild if offsets exceed the file's logical size.","Align writer/reader versions so offset layouts match."],"exampleFix":"// before\nlegacy.readFully(offsetFromIndex, buf);\n// after\nif (offsetFromIndex < 0 || offsetFromIndex > legacy.writeOutBytes) {\n  throw new IllegalStateException(\"invalid offset \" + offsetFromIndex);\n}\nlegacy.readFully(offsetFromIndex, buf);","handlingStrategy":"validation","validationCode":"if (offset < 0 || offset > legacy.writeOutBytes) throw new IllegalArgumentException(\"offset out of range: \" + offset);","typeGuard":null,"tryCatchPattern":"try { legacy.readFully(pos, buf); } catch (IllegalArgumentException e) { throw new IOException(\"bad offset \" + pos, e); }","preventionTips":["Only use offsets obtained from the current writer instance.","Confirm logical size with flush() before range reads.","Version-check legacy vs current segment formats.","Validate on-disk size against index metadata before reading."],"tags":["segment-writeout","range-check","offset","legacy"],"backgroundTag":"value-out-of-range","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"}