{"record":{"id":"045e7ce14934b4bc","repo":"apache/beam","slug":"caller-does-not-own-the-underlying-input-stream-and-should-045e7c","errorCode":null,"errorMessage":"Caller does not own the underlying input stream  and should not call reset().","messagePattern":"Caller does not own the underlying input stream  and should not call reset\\(\\)\\.","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"sdks/java/core/src/main/java/org/apache/beam/sdk/util/UnownedInputStream.java","lineNumber":73,"sourceCode":"    return in.hashCode();\n  }\n\n  @SuppressWarnings(\"UnsynchronizedOverridesSynchronized\")\n  @Override\n  public void mark(int readlimit) {\n    throw new UnsupportedOperationException(\n        \"Caller does not own the underlying input stream \" + \" and should not call mark().\");\n  }\n\n  @Override\n  public boolean markSupported() {\n    return false;\n  }\n\n  @SuppressWarnings(\"UnsynchronizedOverridesSynchronized\")\n  @Override\n  public void reset() throws IOException {\n    throw new UnsupportedOperationException(\n        \"Caller does not own the underlying input stream \" + \" and should not call reset().\");\n  }\n\n  @Override\n  public String toString() {\n    return MoreObjects.toStringHelper(UnownedInputStream.class).add(\"in\", in).toString();\n  }\n}\n","sourceCodeStart":55,"sourceCodeEnd":82,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/core/src/main/java/org/apache/beam/sdk/util/UnownedInputStream.java#L55-L82","documentation":"UnownedInputStream wraps an InputStream the caller does not own, so reset() is deliberately unsupported: resetting would reposition a stream shared with other code. The library throws UnsupportedOperationException to signal a programming/API-contract mistake rather than an I/O failure.","triggerScenarios":"Calling reset() on a UnownedInputStream (e.g. one obtained from a source that handed you a stream it still manages, such as FileIO ReadableFile.open() results in some pipelines), or code that calls reset() after mark() via generic stream-handling logic.","commonSituations":"Generic pipeline code that assumes every InputStream supports reset (e.g. compression/checksum layers or retry logic that rewinds); passing a wrapped stream to a library that calls reset() for re-reads.","solutions":["Do not call reset() on this stream; it is a contract violation, not a recoverable error","If you need mark/reset, buffer the bytes yourself: read the stream into a byte[] or wrap in a BufferedInputStream (with adequate size) that you own","Open your own independent stream from the underlying resource if a re-read is required","Check java.io.InputStream.markSupported() before calling reset() in generic code"],"exampleFix":"// before\nstream.mark(1 << 20);\nconsume(stream);\nstream.reset();\n// after\nbyte[] bytes = ByteStreams.toByteArray(stream);\nconsume(new ByteArrayInputStream(bytes));\nconsume(new ByteArrayInputStream(bytes));","handlingStrategy":"try-catch","validationCode":"if (stream.markSupported()) { stream.reset(); } else { /* re-open or buffer instead */ }","typeGuard":"static boolean resettable(InputStream s) { return !(s instanceof UnownedInputStream) && s.markSupported(); }","tryCatchPattern":"try { stream.reset(); } catch (UnsupportedOperationException e) { // stream not owned: re-open source or use a buffered copy }","preventionTips":["Never call reset() on streams you did not open","Check markSupported() before mark/reset","Buffer into byte[]/ByteArrayInputStream when multiple passes are needed"],"tags":["java","io","unsupported-operation","stream"],"backgroundTag":"unsupported-operation","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T21:17:11.552Z"}