{"record":{"id":"7fa1b6c93ee66a23","repo":"apache/beam","slug":"caller-does-not-own-the-underlying-output-stream-and-should","errorCode":null,"errorMessage":"Caller does not own the underlying output stream  and should not call close().","messagePattern":"Caller does not own the underlying output stream  and should not call close\\(\\)\\.","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"sdks/java/core/src/main/java/org/apache/beam/sdk/util/UnownedOutputStream.java","lineNumber":39,"sourceCode":"import java.io.IOException;\nimport java.io.OutputStream;\nimport org.apache.beam.sdk.annotations.Internal;\nimport org.apache.beam.vendor.guava.v32_1_2_jre.com.google.common.base.MoreObjects;\nimport org.checkerframework.checker.nullness.qual.Nullable;\n\n/**\n * A {@link OutputStream} wrapper which protects against the user attempting to modify the\n * underlying stream by closing it.\n */\n@Internal\npublic class UnownedOutputStream extends FilterOutputStream {\n  public UnownedOutputStream(OutputStream delegate) {\n    super(delegate);\n  }\n\n  @Override\n  public void close() throws IOException {\n    throw new UnsupportedOperationException(\n        \"Caller does not own the underlying output stream \" + \" and should not call close().\");\n  }\n\n  @Override\n  public boolean equals(@Nullable Object obj) {\n    return obj instanceof UnownedOutputStream && ((UnownedOutputStream) obj).out.equals(out);\n  }\n\n  @Override\n  public int hashCode() {\n    return out.hashCode();\n  }\n\n  @Override\n  public String toString() {\n    return MoreObjects.toStringHelper(UnownedOutputStream.class).add(\"out\", out).toString();\n  }\n","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/core/src/main/java/org/apache/beam/sdk/util/UnownedOutputStream.java#L21-L57","documentation":"UnownedOutputStream wraps an OutputStream the caller does not own; close() is intentionally unsupported because closing would also close a stream shared with other code (e.g. a file channel managed by Beam). The wrapper forwards writes but delegates lifecycle management to the owner.","triggerScenarios":"Calling close() on a UnownedInputStream-style wrapper (e.g. channels.newOutputStream(...) wrapped streams returned by Beam APIs) or using try-with-resources on such a stream, whose implicit close() triggers the exception.","commonSituations":"try-with-resources around an output stream obtained from a Beam file/channel API; utility code that always closes OutputStream arguments; nested stream chains where an outer wrapper closes inner streams.","solutions":["Do not close the wrapper; close only the underlying stream you actually own, after you are done writing","Flush the wrapper explicitly instead of relying on close() to flush","Avoid try-with-resources on the wrapper; manage the owner stream's lifecycle yourself","If you must hand it to a close-happy API, pass your own stream and copy to the unowned one"],"exampleFix":"// before\ntry (OutputStream out = new UnownedOutputStream(rawOut)) {\n  writeData(out);\n}\n// after\nOutputStream out = new UnownedOutputStream(rawOut);\nwriteData(out);\nout.flush();\n// close rawOut only when you own it","handlingStrategy":"try-catch","validationCode":"if (out instanceof UnownedOutputStream) { /* do not close; flush only */ }","typeGuard":"static boolean closable(OutputStream o) { return !(o instanceof UnownedOutputStream); }","tryCatchPattern":"try { out.close(); } catch (UnsupportedOperationException e) { // ownership violation: close only the underlying owner stream }","preventionTips":["Do not use try-with-resources on unowned streams","Call flush() instead of relying on close()","Track stream ownership explicitly in utility APIs"],"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"}