apache/beam · error · UnsupportedOperationException

Caller does not own the underlying input stream and should

Error message

Caller does not own the underlying input stream  and should not call reset().

What it means

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.

Source

Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/util/UnownedInputStream.java:73

    return in.hashCode();
  }

  @SuppressWarnings("UnsynchronizedOverridesSynchronized")
  @Override
  public void mark(int readlimit) {
    throw new UnsupportedOperationException(
        "Caller does not own the underlying input stream " + " and should not call mark().");
  }

  @Override
  public boolean markSupported() {
    return false;
  }

  @SuppressWarnings("UnsynchronizedOverridesSynchronized")
  @Override
  public void reset() throws IOException {
    throw new UnsupportedOperationException(
        "Caller does not own the underlying input stream " + " and should not call reset().");
  }

  @Override
  public String toString() {
    return MoreObjects.toStringHelper(UnownedInputStream.class).add("in", in).toString();
  }
}

View on GitHub (pinned to 12126d8942)

Solutions

  1. Do not call reset() on this stream; it is a contract violation, not a recoverable error
  2. 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
  3. Open your own independent stream from the underlying resource if a re-read is required
  4. Check java.io.InputStream.markSupported() before calling reset() in generic code

Example fix

// before
stream.mark(1 << 20);
consume(stream);
stream.reset();
// after
byte[] bytes = ByteStreams.toByteArray(stream);
consume(new ByteArrayInputStream(bytes));
consume(new ByteArrayInputStream(bytes));
Defensive patterns

Strategy: try-catch

Validate before calling

if (stream.markSupported()) { stream.reset(); } else { /* re-open or buffer instead */ }

Type guard

static boolean resettable(InputStream s) { return !(s instanceof UnownedInputStream) && s.markSupported(); }

Try / catch

try { stream.reset(); } catch (UnsupportedOperationException e) { // stream not owned: re-open source or use a buffered copy }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

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


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/045e7ce14934b4bc. Report an issue: GitHub.