{"record":{"id":"31caabd1fcbf0887","repo":"apache/beam","slug":"forbidden-ioexception-when-writing-to-outputstream","errorCode":null,"errorMessage":"Forbidden IOException when writing to OutputStream","messagePattern":"Forbidden IOException when writing to OutputStream","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdks/java/core/src/main/java/org/apache/beam/sdk/util/CoderUtils.java","lineNumber":89,"sourceCode":"        return stream.toByteArray();\n      } finally {\n        threadLocalOutputStreamInUse.set(false);\n      }\n    }\n  }\n\n  /**\n   * Encodes {@code value} to the given {@code stream}, which should be a stream that never throws\n   * {@code IOException}, such as {@code ByteArrayOutputStream} or {@link\n   * ExposedByteArrayOutputStream}.\n   */\n  private static <T> void encodeToSafeStream(\n      Coder<T> coder, T value, OutputStream stream, Coder.Context context) throws CoderException {\n    try {\n      coder.encode(value, new UnownedOutputStream(stream), context);\n    } catch (IOException exn) {\n      Throwables.propagateIfPossible(exn, CoderException.class);\n      throw new IllegalArgumentException(\"Forbidden IOException when writing to OutputStream\", exn);\n    }\n  }\n\n  /** Decodes the given bytes using the specified Coder, and returns the resulting decoded value. */\n  public static <T> T decodeFromByteArray(Coder<T> coder, byte[] encodedValue)\n      throws CoderException {\n    return decodeFromByteArray(coder, encodedValue, Coder.Context.OUTER);\n  }\n\n  public static <T> T decodeFromByteArray(\n      Coder<T> coder, byte[] encodedValue, Coder.Context context) throws CoderException {\n    try (ExposedByteArrayInputStream stream = new ExposedByteArrayInputStream(encodedValue)) {\n      T result = decodeFromSafeStream(coder, stream, context);\n      if (stream.available() != 0) {\n        throw new CoderException(\n            stream.available() + \" unexpected extra bytes after decoding \" + result);\n      }\n      return result;","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/core/src/main/java/org/apache/beam/sdk/util/CoderUtils.java#L71-L107","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\npublic void encode(T value, OutputStream out, Context ctx) throws IOException {\n  myMaybeClosedStream.write(...); // throws IOException\n}\n// after\npublic void encode(T value, OutputStream out, Context ctx) throws CoderException {\n  try {\n    out.write(...);\n  } catch (IOException e) {\n    throw new CoderException(\"encode failed for value: \" + value, e);\n  }\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  byte[] bytes = CoderUtils.encodeToByteArray(coder, value);\n} catch (IllegalArgumentException e) {\n  throw new IllegalStateException(\"Coder/stream contract violation\", e.getCause());\n}","preventionTips":["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"],"tags":["java","io","coders","serialization"],"backgroundTag":"unexpected-io-error","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}