apache/beam · error · IllegalArgumentException
Forbidden IOException when writing to OutputStream
Error message
Forbidden IOException when writing to OutputStream
What it means
CoderUtils.encodeToSafeStream encodes a value with a Coder over an UnownedOutputStream and asserts that coding should never raise a raw IOException. If one escapes (and is not a CoderException), it is rethrown as IllegalArgumentException with this message. It signals a coder bug or an underlying stream failure that the safe-encode contract does not expect.
Source
Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/util/CoderUtils.java:89
return stream.toByteArray();
} finally {
threadLocalOutputStreamInUse.set(false);
}
}
}
/**
* Encodes {@code value} to the given {@code stream}, which should be a stream that never throws
* {@code IOException}, such as {@code ByteArrayOutputStream} or {@link
* ExposedByteArrayOutputStream}.
*/
private static <T> void encodeToSafeStream(
Coder<T> coder, T value, OutputStream stream, Coder.Context context) throws CoderException {
try {
coder.encode(value, new UnownedOutputStream(stream), context);
} catch (IOException exn) {
Throwables.propagateIfPossible(exn, CoderException.class);
throw new IllegalArgumentException("Forbidden IOException when writing to OutputStream", exn);
}
}
/** Decodes the given bytes using the specified Coder, and returns the resulting decoded value. */
public static <T> T decodeFromByteArray(Coder<T> coder, byte[] encodedValue)
throws CoderException {
return decodeFromByteArray(coder, encodedValue, Coder.Context.OUTER);
}
public static <T> T decodeFromByteArray(
Coder<T> coder, byte[] encodedValue, Coder.Context context) throws CoderException {
try (ExposedByteArrayInputStream stream = new ExposedByteArrayInputStream(encodedValue)) {
T result = decodeFromSafeStream(coder, stream, context);
if (stream.available() != 0) {
throw new CoderException(
stream.available() + " unexpected extra bytes after decoding " + result);
}
return result;View on GitHub (pinned to 12126d8942)
Solutions
- Inspect the cause chain (exn.getCause()) to find the real IOException source
- Fix the custom Coder so encode() only throws CoderException for value-level problems
- Ensure the target OutputStream is open and healthy before calling CoderUtils.encodeToByteArray
- Wrap known-fragile coder calls and surface the underlying IOException with context
Example fix
// before
public void encode(T value, OutputStream out, Context ctx) throws IOException {
myMaybeClosedStream.write(...); // throws IOException
}
// after
public void encode(T value, OutputStream out, Context ctx) throws CoderException {
try {
out.write(...);
} catch (IOException e) {
throw new CoderException("encode failed for value: " + value, e);
}
} Defensive patterns
Strategy: try-catch
Try / catch
try {
byte[] bytes = CoderUtils.encodeToByteArray(coder, value);
} catch (IllegalArgumentException e) {
throw new IllegalStateException("Coder/stream contract violation", e.getCause());
} Prevention
- Implement custom Coders per the contract: only CoderException for value problems
- Never encode to streams you don't own or that may be closed
- Log the full cause chain when this fires
- Test custom coders round-trip with CoderUtils
When it happens
Trigger: A custom Coder's encode() implementation throws IOException for reasons other than malformed values (e.g. writes to a wrapped stream that fails); a coder writing to a stream already closed or in an error state.
Common situations: Custom coder implementations propagating stream I/O errors; closed or broken underlying output streams; coder implementations violating the contract that encoding to an unowned stream must not fail with IOException.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Cannot provide SerializableCoder because {} does not impleme
- Java Serialization may be non-deterministic.
- unexpected extra bytes after decoding
- Forbidden IOException when reading from InputStream
- cannot encode a null Integer
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/31caabd1fcbf0887.
Report an issue: GitHub.