{"record":{"id":"d014d95962ec368d","repo":"apache/druid","slug":"corrupt-frame-file-frame-d-location-out-of-ra","errorCode":null,"errorMessage":"Corrupt frame file: frame [%,d] location out of range","messagePattern":"Corrupt frame file: frame \\[%,d\\] location out of range","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/frame/file/FrameFileFooter.java","lineNumber":112,"sourceCode":"  }\n\n  /**\n   * Get the last byte for the frame specified. The byte number is offsetted from the frame file start and is exclusive.\n   * @param frameNumber the id of the frame to get the end position for\n   * @return a long exclusive index representing the frame end\n   */\n  public long getFrameEndPosition(final int frameNumber)\n  {\n    assert frameNumber >= 0 && frameNumber < numFrames;\n\n    final long frameEndPointerPosition =\n        footerMemory.getCapacity() - FrameFileWriter.TRAILER_LENGTH - (long) (numFrames - frameNumber) * Long.BYTES;\n\n    final long frameEndPosition = footerMemory.getLong(frameEndPointerPosition);\n\n    // Bounds check: protect against possibly-corrupt data.\n    if (frameEndPosition < 0 || frameEndPosition > frameFileLength - footerMemory.getCapacity()) {\n      throw new ISE(\"Corrupt frame file: frame [%,d] location out of range\", frameNumber);\n    }\n\n    return frameEndPosition;\n  }\n\n  public int getNumFrames()\n  {\n    return numFrames;\n  }\n\n  public int getNumPartitions()\n  {\n    return numPartitions;\n  }\n}\n","sourceCodeStart":94,"sourceCodeEnd":128,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/frame/file/FrameFileFooter.java#L94-L128","documentation":"getFrameEndPosition reads a frame's end offset from the footer and bounds-checks it against the frame-data region of the file. An out-of-range value (negative or beyond the data region) means the footer's frame pointer table is corrupt, so it throws instead of returning a bogus offset.","triggerScenarios":"Calling getFrameEndPosition (directly or via startByte/endByte) on a frame file whose footer frame-end table was corrupted, truncated, or written inconsistently — the stored long is negative or exceeds fileLength - footerSize.","commonSituations":"Reading a frame file damaged by a partial write or crash; accessing a specific frame index in a file that failed footer validation edge cases; disk corruption on deep storage.","solutions":["Regenerate the frame file from the producing job; the pointer table cannot be trusted or reconstructed safely.","Re-read the file from a different replica/deep-storage location if available.","Check the storage layer (disk errors, S3 integrity) if corruption recurs.","Validate the whole file (footer checksum, open()) before iterating frames to fail earlier with a clearer error."],"exampleFix":"// before\nlong pos = footer.startByte(frameNumber); // ISE for corrupt table\n// after\n// open() already validates the footer checksum; prefer fully validating first\ntry (FrameFile.Entry entry = FrameFile.open(file, maxMmapSize)) {\n  long pos = entry.footer().startByte(frameNumber);\n} catch (IllegalStateException e) {\n  regenerateFrameFile(file); // corrupt pointer table: rebuild\n}","handlingStrategy":"validation","validationCode":"FrameFile.Entry entry = FrameFile.open(file, maxMmapSize); // validates footer first\nFrameFileFooter footer = entry.footer();\nif (frameNumber < 0 || frameNumber >= footer.getNumFrames()) {\n  throw new IndexOutOfBoundsException(\"frameNumber=\" + frameNumber);\n}","typeGuard":"static boolean isValidFrameIndex(FrameFileFooter footer, int frameNumber) {\n  return frameNumber >= 0 && frameNumber < footer.getNumFrames();\n}","tryCatchPattern":"try {\n  long end = footer.endByte(frameNumber);\n} catch (IllegalStateException e) {\n  if (e.getMessage().contains(\"location out of range\")) {\n    // corrupt pointer table: switch to a replica or regenerate\n    throw new IllegalStateException(\"Frame pointers corrupt: \" + file, e);\n  }\n  throw e;\n}","preventionTips":["Always open/validate the whole frame file before random frame access.","Keep frame indices within [0, numFrames).","Verify file integrity from deep storage if out-of-range errors appear.","Maintain single-writer, publish-after-complete output discipline."],"tags":["io","corruption","druid"],"backgroundTag":"checksum-mismatch","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"}