{"record":{"id":"4933a209f576fb33","repo":"apache/druid","slug":"startframe-d-endframe-d","errorCode":null,"errorMessage":"startFrame[%,d] > endFrame[%,d]","messagePattern":"startFrame\\[%,d\\] > endFrame\\[%,d\\]","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/frame/channel/ReadableFileFrameChannel.java","lineNumber":63,"sourceCode":"\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  }\n\n  @Override\n  public boolean isFinished()\n  {","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/frame/channel/ReadableFileFrameChannel.java#L45-L81","documentation":"The constructor also requires startFrame <= endFrame; an inverted range selects no frames validly and is treated as a caller bug, throwing IAE. This prevents silently reading nothing or misadvancing frame cursors.","triggerScenarios":"Constructing ReadableFileFrameChannel with startFrame > endFrame, e.g. swapped arguments or a partition range computed from wrong ordering.","commonSituations":"Swapping parameter order at call sites; partition-assignment code emitting reversed ranges; off-by-one logic where start is computed after end.","solutions":["Swap or recompute the range so startFrame <= endFrame.","Validate partition ranges before constructing the channel.","Check the partition-assignment logic for argument ordering bugs."],"exampleFix":"// before\nnew ReadableFileFrameChannel(frameFile, deserializer, endFrame, startFrame); // swapped\n// after\nnew ReadableFileFrameChannel(frameFile, deserializer, startFrame, endFrame);","handlingStrategy":"validation","validationCode":"if (startFrame > endFrame) { throw new IllegalArgumentException(\"startFrame must be <= endFrame\"); }","typeGuard":"boolean validRange(int startFrame, int endFrame) { return startFrame >= 0 && startFrame <= endFrame; }","tryCatchPattern":"try { new ReadableFileFrameChannel(f, d, startFrame, endFrame); } catch (IAE e) { if (e.getMessage().contains(\"> endFrame\")) { /* fix range ordering and retry */ } else { throw e; } }","preventionTips":["Validate start <= end wherever frame ranges are computed.","Keep constructor argument order consistent at call sites.","Assert ranges in partition-assignment code paths."],"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"}