oracle/graal · error · IllegalStateException
Trying to write during graph print.
Error message
Trying to write during graph print.
What it means
GraphProtocol implements WritableByteChannel; while a graph print is executing (printing flag set during print/beginGroup/endGroup/startDocument), the channel is in a protocol-controlled state and raw writes would interleave garbage into the structured stream. write(ByteBuffer) therefore throws IllegalStateException if called mid-print. Only bytes written between print operations (e.g. via flushEmbedded boundaries) are legal.
Source
Thrown at compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/graphio/GraphProtocol.java:180
flushEmbedded();
} finally {
printing = false;
}
}
public final void endGroup() throws IOException {
printing = true;
try {
writeByte(CLOSE_GROUP);
flushEmbedded();
} finally {
printing = false;
}
}
final int write(ByteBuffer src) throws IOException {
if (printing) {
throw new IllegalStateException("Trying to write during graph print.");
}
constantPool.reset();
return writeBytesRaw(src);
}
final boolean isOpen() {
return channel.isOpen();
}
@Override
public final void close() {
try {
flush();
channel.close();
} catch (IOException ex) {
throw new Error(ex);
}
}View on GitHub (pinned to a66e9ccd1d)
Solutions
- Serialize all access to the channel: synchronize on the GraphOutput/GraphProtocol so raw writes never overlap print calls.
- Move custom byte emission to after endGroup/print completes (between top-level dump operations).
- Give each concurrent producer its own GraphOutput rather than multiplexing one channel.
Example fix
// before
new Thread(() -> channel.write(myBuffer)).start(); // may run during print
output.print(graph, ...);
// after
synchronized (output) {
output.print(graph, ...);
channel.write(myBuffer); // only between print operations
} Defensive patterns
Strategy: try-catch
Validate before calling
// serialize all channel access around the GraphOutput
synchronized (output) {
output.print(graph, ...);
}
synchronized (output) {
channel.write(rawBuffer); // only between print operations
} Try / catch
try {
channel.write(buf);
} catch (IllegalStateException e) {
if (e.getMessage().contains("during graph print")) {
// a print is in flight on another thread: wait for the dump lock and retry once
synchronized (output) { channel.write(buf); }
} else throw e;
} Prevention
- Give each writer thread its own GraphOutput; never share one channel across producers.
- Wrap every channel operation in the same lock that guards print calls.
- Emit custom framing bytes only between top-level dump operations.
When it happens
Trigger: Another thread using the same channel while a dump is in progress; or application code writing custom bytes through the channel from inside a graph-printing callback. Embedding the GraphProtocol channel inside another protocol and writing to it during a nested print call.
Common situations: Sharing one GraphOutput/channel across threads without synchronization. Custom dump listeners that also emit data on the channel. Building composite dump formats where raw framing bytes are written around, but accidentally during, graph sections.
Related errors
- Expecting
- Cannot downgrade from minimum required version
- Feature unsupported in version
- Dump properties unsupported in format v.
- Too many nodes in list:
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/1a21e0b580290538.
Report an issue: GitHub.