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

  1. Regenerate the replay file with a build whose codec never writes null for that field
  2. Verify version compatibility before decode
  3. 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 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


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