oracle/graal · error · IOException
Unknown field
Error message
Unknown field
What it means
Thrown when decoding a FIELD_TAG: the codec reflectively resolves a declared field by holder class and name (with special-casing for String.coder/value), and getDeclaredField throws NoSuchFieldException. The IOException 'Unknown field <holder>.<name>' means the field existed when the replay was recorded but not in the replaying JVM's classes.
Source
Thrown at compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/BinaryReplayCodec.java:905
case STACK_TRACE_ELEMENT_TAG ->
new StackTraceElement(readStringReference(in, state), readStringReference(in, state),
readStringReference(in, state), requireNonNullString(readStringReference(in, state), "stack trace holder"),
requireNonNullString(readStringReference(in, state), "stack trace method"), readStringReference(in, state), in.readPackedSignedInt());
case REGISTER_TAG -> findRegister(state.registerArchitecture(), in.readPackedUnsignedInt());
case FIELD_TAG -> {
Class<?> holder = ReplayTypeSupport.classCast(ReplayTypeSupport.decodeClass(requireNonNullString(readStringReference(in, state), "field holder")));
String name = requireNonNullString(readStringReference(in, state), "field name");
try {
if (holder == String.class) {
if ("coder".equals(name)) {
yield String.class.getDeclaredField("coder");
} else if ("value".equals(name)) {
yield String.class.getDeclaredField("value");
}
}
yield holder.getDeclaredField(name);
} catch (NoSuchFieldException e) {
throw new IOException("Unknown field " + holder.getName() + "." + name, e);
}
}
case ASSUMPTION_RESULT_TAG -> {
Object result = readValue(in, state);
int length = in.readPackedUnsignedInt();
Assumptions.Assumption[] assumptions = new Assumptions.Assumption[length];
for (int i = 0; i < length; i++) {
assumptions[i] = (Assumptions.Assumption) readValue(in, state);
}
yield new Assumptions.AssumptionResult<>(result, assumptions);
}
case ASSUMPTION_TAG -> switch (in.readPackedUnsignedInt()) {
case ASSUMPTION_NO_FINALIZABLE_SUBCLASS ->
new Assumptions.NoFinalizableSubclass((ResolvedJavaType) readValue(in, state));
case ASSUMPTION_CONCRETE_SUBTYPE -> {
ResolvedJavaType subtype = (ResolvedJavaType) readValue(in, state);
ResolvedJavaType context = (ResolvedJavaType) readValue(in, state);
yield new DelayedDeserializationObject.ConcreteSubtypeWithDelayedDeserialization(context, subtype);View on GitHub (pinned to a66e9ccd1d)
Solutions
- Re-record the replay file on the same JDK + GraalVM build used for replay
- Verify the field exists: check holder.getDeclaredField(name) in the replaying environment
- If the field genuinely moved, add a resolution case in the FIELD_TAG branch (as done for String 'coder'/'value')
Example fix
// before
yield holder.getDeclaredField(name); // NoSuchFieldException -> IOException: Unknown field
// after
// special-case relocated fields, mirroring the String handling
if (holder == SomeClass.class && "oldName".equals(name)) {
yield SomeClass.class.getDeclaredField("newName");
}
yield holder.getDeclaredField(name); Defensive patterns
Strategy: validation
Validate before calling
static boolean fieldResolvable(Class<?> holder, String name) {
try { holder.getDeclaredField(name); return true; }
catch (NoSuchFieldException e) { return false; }
} Try / catch
try {
result = codec.readReplay(in);
} catch (IOException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Unknown field")) {
// JDK/class version skew: re-record on this JDK
} else throw e;
} Prevention
- Replay with the same JDK version that recorded the file
- When renaming a recorded field, add a compatibility case in the FIELD_TAG branch like the String coder/value handling
When it happens
Trigger: Replaying against a JDK/compiler build where the field was renamed, removed, or moved to a superclass; the stream is corrupt so the field-name string decodes to garbage.
Common situations: JDK version differences (e.g. String internals changing across JDK releases); replaying files recorded on a GraalVM development build carrying renamed fields; classpath shadowing loading an older class version.
Related errors
- Unknown enum constant for
- Unknown replay marker kind
- Unknown replay assumption kind
- Unknown replay tag
- Invalid replay boolean flag
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/9ae83d1e42497b38.
Report an issue: GitHub.