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

  1. Serialize all access to the channel: synchronize on the GraphOutput/GraphProtocol so raw writes never overlap print calls.
  2. Move custom byte emission to after endGroup/print completes (between top-level dump operations).
  3. 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

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


AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14). Data as JSON: /api/errors/1a21e0b580290538. Report an issue: GitHub.