{"record":{"id":"462508129f8b528e","repo":"apache/iceberg","slug":"no-mark-defined","errorCode":null,"errorMessage":"No mark defined","messagePattern":"No mark defined","errorType":"exception","errorClass":"java.io.IOException","httpStatus":null,"severity":"warning","filePath":"core/src/main/java/org/apache/iceberg/io/SingleBufferInputStream.java","lineNumber":189,"sourceCode":"\n    ByteBuffer remaining = buffer.duplicate();\n    buffer.position(buffer.limit());\n\n    return Collections.singletonList(remaining);\n  }\n\n  @Override\n  public void mark(int readlimit) {\n    this.mark = buffer.position();\n  }\n\n  @Override\n  public void reset() throws IOException {\n    if (mark >= 0) {\n      buffer.position(mark);\n      this.mark = -1;\n    } else {\n      throw new IOException(\"No mark defined\");\n    }\n  }\n\n  @Override\n  public boolean markSupported() {\n    return true;\n  }\n\n  @Override\n  public int available() {\n    return buffer.remaining();\n  }\n}\n","sourceCodeStart":171,"sourceCodeEnd":203,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/io/SingleBufferInputStream.java#L171-L203","documentation":"SingleBufferInputStream.reset() restores the stream to the position captured by mark(), but the mark is cleared after a single reset and mark is only set by an explicit call. IOException \"No mark defined\" is thrown when reset() is called without a preceding mark() call, or after the mark has already been consumed/reset once.","triggerScenarios":"Calling reset() before calling mark(pos), or calling reset() twice without re-marking, or after the underlying read consumed the marked state.","commonSituations":"Code ported from streams assumed mark() was implicit; retries that call reset() twice to rewind; copy/paste of stream logic where the first reset succeeded and a second one fails.","solutions":["Call mark(position) before reset(); re-mark after each reset if you need to rewind again.","Restructure the reader to track its own position and use seek() instead of mark/reset.","Wrap reset() in a check of markSupported()/your own saved position rather than relying on repeated resets.","If repeat rewinding is needed, duplicate the stream or re-create it from the source ByteBuffer."],"exampleFix":"// before\nstream.reset(); stream.reset(); // second reset: No mark defined\n\n// after\nstream.mark(0);\nstream.reset();\nstream.mark(0); // re-mark before resetting again\nstream.reset();","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  stream.reset();\n} catch (IOException e) {\n  if (\"No mark defined\".equals(e.getMessage())) {\n    stream.seek(savedPosition); // rewind via explicit position instead\n  } else {\n    throw e;\n  }\n}","preventionTips":["Always call mark(position) immediately before any planned reset()","Remember mark is one-shot: re-mark after each reset if rewinding repeatedly","Prefer seek(pos) over mark/reset for repeatable rewinds on this stream"],"tags":["mark-reset","input-stream","stream-state"],"backgroundTag":"invalid-state-transition","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}