apache/beam · error · UnsupportedOperationException
Caller does not own the underlying output stream and should
Error message
Caller does not own the underlying output stream and should not call close().
What it means
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.
Source
Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/util/UnownedOutputStream.java:39
import java.io.IOException;
import java.io.OutputStream;
import org.apache.beam.sdk.annotations.Internal;
import org.apache.beam.vendor.guava.v32_1_2_jre.com.google.common.base.MoreObjects;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* A {@link OutputStream} wrapper which protects against the user attempting to modify the
* underlying stream by closing it.
*/
@Internal
public class UnownedOutputStream extends FilterOutputStream {
public UnownedOutputStream(OutputStream delegate) {
super(delegate);
}
@Override
public void close() throws IOException {
throw new UnsupportedOperationException(
"Caller does not own the underlying output stream " + " and should not call close().");
}
@Override
public boolean equals(@Nullable Object obj) {
return obj instanceof UnownedOutputStream && ((UnownedOutputStream) obj).out.equals(out);
}
@Override
public int hashCode() {
return out.hashCode();
}
@Override
public String toString() {
return MoreObjects.toStringHelper(UnownedOutputStream.class).add("out", out).toString();
}
View on GitHub (pinned to 12126d8942)
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
Example fix
// before
try (OutputStream out = new UnownedOutputStream(rawOut)) {
writeData(out);
}
// after
OutputStream out = new UnownedOutputStream(rawOut);
writeData(out);
out.flush();
// close rawOut only when you own it Defensive patterns
Strategy: try-catch
Validate before calling
if (out instanceof UnownedOutputStream) { /* do not close; flush only */ } Type guard
static boolean closable(OutputStream o) { return !(o instanceof UnownedOutputStream); } Try / catch
try { out.close(); } catch (UnsupportedOperationException e) { // ownership violation: close only the underlying owner stream } Prevention
- Do not use try-with-resources on unowned streams
- Call flush() instead of relying on close()
- Track stream ownership explicitly in utility APIs
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Caller does not own the underlying input stream and should
- Must resolve compression into a concrete value before callin
- AUTO is applicable only to reading files
- Writing ZIP files is currently unsupported
- Stream has been finished. Can not add any more elements.
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/7fa1b6c93ee66a23.
Report an issue: GitHub.