oracle/graal · error · IOException
Required replay field is null
Error message
Required replay field is null
What it means
requireNonNullString is the codec's guard for string fields that must never be null in a valid stream (enum class, field holder, method name, throwables, etc.). When readStringReference returns null for such a position, it throws IOException 'Required replay field <description> is null'. A null here means either the stream explicitly contained a NULL_TAG where a required string was expected, or the reader is misaligned.
Source
Thrown at compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/BinaryReplayCodec.java:1106
private static Object readSpecialSingleton(int kind) throws IOException {
return switch (kind) {
case SINGLETON_NULL_POINTER -> JavaConstant.NULL_POINTER;
case SINGLETON_COMPRESSED_NULL -> HotSpotCompressedNullConstant.COMPRESSED_NULL;
case SINGLETON_NO_SPECULATION -> SpeculationLog.NO_SPECULATION;
case SINGLETON_ILLEGAL_VALUE_KIND -> ValueKind.Illegal;
default -> throw new IOException("Unknown replay singleton kind " + kind);
};
}
private Class<?> arrayComponentType(Object[] array) {
Class<?> componentType = array.getClass().getComponentType();
Class<?> registeredSupertype = declarations.findRegisteredSupertype(componentType);
return (registeredSupertype != null) ? registeredSupertype : componentType;
}
private static String requireNonNullString(String value, String description) throws IOException {
if (value == null) {
throw new IOException("Required replay field " + description + " is null");
}
return value;
}
private static Register findRegister(Architecture architecture, int number) throws IOException {
for (Register register : architecture.getRegisters()) {
if (register.number == number) {
return register;
}
}
throw new IOException("Register " + number + " not found in " + architecture.getName());
}
private static Throwable createThrowable(String className, String message) {
if (className.equals(JVMCIError.class.getName())) {
return new JVMCIError(message);
} else if (className.equals(GraalError.class.getName())) {
return new GraalError(message);View on GitHub (pinned to a66e9ccd1d)
Solutions
- Regenerate the replay file with a build whose codec never writes null for that field
- Verify version compatibility before decode
- If writing a codec extension, never emit NULL_TAG for fields documented as required
Defensive patterns
Strategy: validation
Validate before calling
// on the writer side: never write null for required string fields
static void writeRequiredString(ObjectCopierOutputStream out, String s) {
if (s == null) throw new IllegalStateException("required string must not be null");
// ... write reference
} Try / catch
try {
result = codec.readReplay(in);
} catch (IOException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Required replay field")) {
// malformed recording: re-record the file
} else throw e;
} Prevention
- When extending the codec, treat names/classes/holders as mandatory non-null strings
- Round-trip test every new record type to prove no null sneaks into required positions
When it happens
Trigger: A NULL_TAG appearing where the format mandates a string (writer bug or hand-crafted stream); misaligned reads after an earlier decode discrepancy; a recording bug that serialized a null name/class.
Common situations: Replaying files from an experimental build that allowed null where the current format forbids it; corrupted streams after truncation.
Related errors
- Invalid replay boolean flag
- Unknown enum constant for
- Unknown replay marker kind
- Unknown field
- Unknown replay assumption kind
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/f24e4474e7263a2a.
Report an issue: GitHub.