{"record":{"id":"4a41e97ab28d7436","repo":"apache/druid","slug":"pos-d-out-of-range-d-d","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/ByteBufferWriteOutBytes.java","lineNumber":210,"sourceCode":"   */\n  public void writeTo(ByteBuffer out)\n  {\n    checkOpen();\n    for (int i = 0; i <= headBufferIndex; i++) {\n      ByteBuffer buffer = buffers.get(i);\n      buffer.flip();\n      out.put(buffer);\n      // switch back to the initial state\n      buffer.limit(buffer.capacity());\n    }\n  }\n\n  @Override\n  public void readFully(long pos, ByteBuffer buffer)\n  {\n    checkOpen();\n    if (pos < 0 || pos > size) {\n      throw new IAE(\"pos %d out of range [%d, %d]\", pos, 0, size);\n    }\n    int ourBufferIndex = Ints.checkedCast(pos / BUFFER_SIZE);\n    int ourBufferOffset = Ints.checkedCast(pos % BUFFER_SIZE);\n    for (int bytesLeft = buffer.remaining(); bytesLeft > 0;) {\n      int bytesToWrite = Math.min(BUFFER_SIZE - ourBufferOffset, bytesLeft);\n      ByteBuffer ourBuffer = buffers.get(ourBufferIndex);\n      int ourBufferPosition = ourBuffer.position();\n      if (bytesToWrite > ourBufferPosition - ourBufferOffset) {\n        throw new BufferUnderflowException();\n      }\n      try {\n        ourBuffer.position(ourBufferOffset);\n        ourBuffer.limit(ourBufferOffset + bytesToWrite);\n        buffer.put(ourBuffer);\n      }\n      finally {\n        // switch back to the initial state\n        ourBuffer.limit(ourBuffer.capacity());","sourceCodeStart":192,"sourceCodeEnd":228,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/segment/writeout/ByteBufferWriteOutBytes.java#L192-L228","documentation":"ByteBufferWriteOutBytes.readFully validates that the requested absolute read position lies within the written data [0, size] before copying bytes into the caller's buffer. It throws IAE when pos is negative or beyond the current size, preventing reads past what has actually been written.","triggerScenarios":"Calling readFully(pos, buffer) with pos < 0, pos > size (e.g. reading before writing finished, stale offset after truncation/rewrite, or offset read from a corrupted header/index).","commonSituations":"Index/offset metadata stored earlier points past the current data (segment rewritten or partially written); off-by-one using size vs size-1; integer overflow of pos; concurrent writers changed size between computing the offset and reading.","solutions":["Verify the pos argument is within [0, size] before calling readFully; recompute or reload offsets from the current writer.","Ensure all writes are complete/flushed (writeIntsealed/write calls done) before reading back; call size() to confirm expected length.","Check for stale or corrupted offset metadata (smile/json index files) and regenerate the segment if offsets exceed size.","Guard against overflow with Ints.checkedCast semantics: confirm pos fits the in-memory buffer sizing model."],"exampleFix":"// before\noutBytes.readFully(offset, buffer); // offset may exceed size after rewrite\n// after\nif (offset < 0 || offset > outBytes.size()) {\n  throw new IllegalStateException(\"stale offset \" + offset + \" > size \" + outBytes.size());\n}\noutBytes.readFully(offset, buffer);","handlingStrategy":"validation","validationCode":"if (pos < 0 || pos > writeOutBytes.size()) throw new IllegalArgumentException(\"pos out of range: \" + pos);","typeGuard":"boolean validPos(WriteOutBytes b, long pos) { return b != null && pos >= 0 && pos <= b.size(); }","tryCatchPattern":"try { out.readFully(pos, buf); } catch (IllegalArgumentException e) { throw new IOException(\"stale offset for read: \" + pos, e); }","preventionTips":["Always derive pos from the same writer instance you read from.","Call size() immediately before readFully to re-validate.","Avoid caching offsets across segment rewrites.","Treat persisted offset metadata as untrusted input; validate before use."],"tags":["segment-writeout","range-check","offset"],"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"}