jwtk/jjwt · error · java.io.IOException
IO Exception ${t.getMessage()}
Error message
IO Exception ${t.getMessage()} What it means
FilteredOutputStream wraps any non-IOException Throwable raised by write, flush, or close on its delegate into an IOException with the message 'IO Exception <msg>'. IOExceptions from the delegate are rethrown as-is.
Source
Thrown at impl/src/main/java/io/jsonwebtoken/impl/io/FilteredOutputStream.java:124
try {
out.flush();
} catch (final Throwable t) {
onThrowable(t);
}
}
/**
* Handle any IOExceptions thrown.
* <p>
* This method provides a point to implement custom exception
* handling. The default behavior is to re-throw the exception.
*
* @param t The Throwable thrown
* @throws IOException if an I/O error occurs.
*/
protected void onThrowable(final Throwable t) throws IOException {
if (t instanceof IOException) throw (IOException) t;
throw new IOException("IO Exception " + t.getMessage(), t);
}
/**
* Invokes the delegate's {@code write(byte[])} method.
*
* @param bts the bytes to write
* @throws IOException if an I/O error occurs.
*/
@Override
public void write(final byte[] bts) throws IOException {
try {
final int len = Bytes.length(bts);
beforeWrite(len);
out.write(bts);
afterWrite(len);
} catch (final Throwable t) {
onThrowable(t);
}View on GitHub (pinned to fb71496164)
Solutions
- Inspect the cause: native IOExceptions surface unchanged, so fix the underlying IO problem.
- Ensure the output stream remains open until all writes and the final flush complete.
- Check flush()/close() ordering — close the stream exactly once, in a finally block or try-with-resources.
- For socket-backed streams, handle broken-pipe conditions on the transport layer.
Example fix
// before
out.write(bytes);
out.flush();
// after
try (OutputStream out = ...) {
out.write(bytes);
out.flush();
} // closes exactly once, even on failure Defensive patterns
Strategy: try-catch
Validate before calling
// Java
if (out == null) throw new IllegalArgumentException("OutputStream cannot be null");
// avoid writing to already-committed servlet responses
if (response != null && response.isCommitted()) throw new IllegalStateException("response committed"); Try / catch
try {
filteredOut.write(bytes);
filteredOut.flush();
} catch (IOException e) {
Throwable cause = e.getCause();
if (cause != null) log.error("Write failure root cause: {}", cause.getMessage());
throw e;
} Prevention
- Close output streams exactly once, using try-with-resources.
- Flush before close; avoid double-close on container-managed streams.
- For socket streams, handle broken pipes at the transport layer.
- Verify delegate streams remain writable throughout the write sequence.
When it happens
Trigger: Writing, flushing, or closing a FilteredOutputStream whose delegate throws a non-IO Throwable (e.g. NullPointerException from an unset delegate, RuntimeException in a custom stream) or an underlying IO error.
Common situations: Output stream closed by the framework before all writes complete; broken pipe on socket-backed streams; flush() on a stream whose target (e.g. HTTP response) is already committed.
Understand the failure class
Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.
Related errors
- Unable to obtain JSON String from Reader:
- Unable to Base64Url-decode InputStream: ${t.getMessage()}
- Unable to ${codecName}-encode ${name}: ${t.getMessage()}
- IO Exception: ${t.getMessage()}
- Unable to read compact JWT: ${e.getMessage()}
AI-assisted analysis of jwtk/jjwt@fb71496164 (2026-09-09).
Data as JSON: /api/errors/c3141ad34814710c.
Report an issue: GitHub.