oracle/graal · error · IllegalArgumentException
Unexpected marker
Error message
Unexpected marker
What it means
Thrown by BinaryReplayCodec.writeValue when a SpecialResultMarker value is neither NO_RESULT_MARKER nor NULL_RESULT_MARKER while serializing a compilation result marker. The codec only knows how to encode those two singleton markers (exception-throwing markers take a different branch), so any other SpecialResultMarker subtype is unencodable. It surfaces as an IllegalArgumentException during writing of a replay file.
Source
Thrown at compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/BinaryReplayCodec.java:589
out.writePackedUnsignedInt(doubles.length);
for (double d : doubles) {
out.writeDoublePrimitive(d);
}
}
case SpecialResultMarker.ExceptionThrownMarker marker -> {
out.write(RESULT_MARKER_TAG);
out.writePackedUnsignedInt(RESULT_EXCEPTION);
writeValue(out, marker.getThrown(), state);
}
case SpecialResultMarker marker -> {
out.write(RESULT_MARKER_TAG);
int markerKind;
if (marker == SpecialResultMarker.NO_RESULT_MARKER) {
markerKind = RESULT_NO_RESULT;
} else if (marker == SpecialResultMarker.NULL_RESULT_MARKER) {
markerKind = RESULT_NULL;
} else {
throw new IllegalArgumentException("Unexpected marker " + marker);
}
out.writePackedUnsignedInt(markerKind);
}
case StackTraceElement ste -> {
out.write(STACK_TRACE_ELEMENT_TAG);
writeStringReference(out, ste.getClassLoaderName(), state);
writeStringReference(out, ste.getModuleName(), state);
writeStringReference(out, ste.getModuleVersion(), state);
writeStringReference(out, ste.getClassName(), state);
writeStringReference(out, ste.getMethodName(), state);
writeStringReference(out, ste.getFileName(), state);
out.writePackedSignedInt(ste.getLineNumber());
}
case Register register -> {
out.write(REGISTER_TAG);
out.writePackedUnsignedInt(register.number);
}
case Field field -> {View on GitHub (pinned to a66e9ccd1d)
Solutions
- If you introduced a new SpecialResultMarker subtype, add a corresponding RESULT_* constant and a write branch (plus a matching read case in the RESULT_MARKER_TAG switch)
- If you control the value, pass only SpecialResultMarker.NO_RESULT_MARKER or NULL_RESULT_MARKER, or use the exception-thrown marker which is handled by its own case
- Check the marker before recording: filter unsupported markers out of the recorded result
Example fix
// before
SpecialResultMarker marker = myCustomMarker; // new subtype
writeValue(out, marker, state);
// after
if (marker == SpecialResultMarker.NO_RESULT_MARKER || marker == SpecialResultMarker.NULL_RESULT_MARKER
|| marker instanceof SpecialResultMarker.ExceptionThrownMarker) {
writeValue(out, marker, state);
} else {
throw new IllegalArgumentException("Unexpected marker " + marker);
} Defensive patterns
Strategy: type-guard
Validate before calling
boolean encodable(SpecialResultMarker m) {
return m == SpecialResultMarker.NO_RESULT_MARKER
|| m == SpecialResultMarker.NULL_RESULT_MARKER
|| m instanceof SpecialResultMarker.ExceptionThrownMarker;
} Type guard
static boolean isEncodableMarker(Object v) {
return v == SpecialResultMarker.NO_RESULT_MARKER
|| v == SpecialResultMarker.NULL_RESULT_MARKER
|| v instanceof SpecialResultMarker.ExceptionThrownMarker;
} Try / catch
try {
codec.writeResult(result);
} catch (IllegalArgumentException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Unexpected marker")) {
// skip recording this result or fail with context
} else throw e;
} Prevention
- Do not create ad-hoc SpecialResultMarker subclasses; use the two singletons and the exception marker
- When adding a new marker kind, update both write and read switches in BinaryReplayCodec and bump VERSION
When it happens
Trigger: Calling the replay writer with a SpecialResultMarker instance that is a new subclass (e.g. a newly added marker kind) or a hand-constructed anonymous subclass; the pattern match 'case SpecialResultMarker marker' falls into the else branch and rejects it.
Common situations: Extending the replay-compilation framework with a new special result marker type without teaching the codec a new RESULT_* kind; passing test doubles or mocks of SpecialResultMarker into recorded compilation results.
Related errors
- No serializer for :
- Unknown registration
- Unexpected architecture ${architecture}
- Unexpected register config ${registerConfig}
- No serializer for ${instanceClass}: ${instance}
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/25e8482aefa57d5a.
Report an issue: GitHub.