{"record":{"id":"506726b4bb23e09b","repo":"apache/druid","slug":"startframe-d-0","errorCode":null,"errorMessage":"startFrame[%,d] < 0","messagePattern":"startFrame\\[%,d\\] < 0","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/frame/channel/ReadableFileFrameChannel.java","lineNumber":59,"sourceCode":"  private final FrameFile frameFile;\n  private final WireTransferable.ConcreteDeserializer deserializer;\n  private final int endFrame;\n  private int currentFrame;\n\n  public ReadableFileFrameChannel(\n      final FrameFile frameFile,\n      final int startFrame,\n      final int endFrame,\n      final WireTransferable.ConcreteDeserializer deserializer\n  )\n  {\n    this.frameFile = frameFile;\n    this.deserializer = deserializer;\n    this.currentFrame = startFrame;\n    this.endFrame = endFrame;\n\n    if (startFrame < 0) {\n      throw new IAE(\"startFrame[%,d] < 0\", startFrame);\n    }\n\n    if (startFrame > endFrame) {\n      throw new IAE(\"startFrame[%,d] > endFrame[%,d]\", startFrame, endFrame);\n    }\n\n    if (endFrame > frameFile.numFrames()) {\n      throw new IAE(\"endFrame[%,d] > numFrames[%,d]\", endFrame, frameFile.numFrames());\n    }\n  }\n\n  public ReadableFileFrameChannel(\n      final FrameFile frameFile,\n      final WireTransferable.ConcreteDeserializer deserializer\n  )\n  {\n    this(frameFile, 0, frameFile.numFrames(), deserializer);\n  }","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/frame/channel/ReadableFileFrameChannel.java#L41-L77","documentation":"ReadableFileFrameChannel reads a range of frames from a FrameFile. The constructor validates that startFrame is non-negative; a negative start frame is meaningless and throws IAE immediately. This is straightforward caller input validation.","triggerScenarios":"Constructing ReadableFileFrameChannel with startFrame < 0, e.g. passing -1 as a sentinel or computing a start index from an empty/underflowed counter.","commonSituations":"Off-by-one arithmetic producing -1 for the first partition; passing default/uninitialized partition metadata; int underflow when deriving frame ranges.","solutions":["Clamp startFrame to 0 before constructing the channel.","Fix the computation producing the negative index (check partition arithmetic).","Validate frame-range inputs at the configuration layer before creating the channel."],"exampleFix":"// before\nnew ReadableFileFrameChannel(frameFile, deserializer, startFrame, endFrame); // startFrame = -1\n// after\nstartFrame = Math.max(0, startFrame);\nnew ReadableFileFrameChannel(frameFile, deserializer, startFrame, endFrame);","handlingStrategy":"validation","validationCode":"if (startFrame < 0) { throw new IllegalArgumentException(\"startFrame must be >= 0: \" + startFrame); }","typeGuard":"boolean validStart(int startFrame) { return startFrame >= 0; }","tryCatchPattern":"try { new ReadableFileFrameChannel(f, d, startFrame, endFrame); } catch (IAE e) { if (e.getMessage().contains(\"startFrame\") && e.getMessage().contains(\"< 0\")) { startFrame = 0; /* retry */ } else { throw e; } }","preventionTips":["Clamp computed start indices to 0.","Validate partition ranges at config/assignment time.","Avoid sentinel -1 values for frame indices."],"tags":["druid","frame-channel","argument-validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}