oracle/graal · error · IOException

Invalid replay file header

Error message

Invalid replay file header

What it means

verifyHeader reads the MAGIC byte sequence at the start of a replay stream; if any byte differs from the expected constant, it throws IOException 'Invalid replay file header'. This is a deliberate fail-fast check that the input is actually a binary replay file produced by this codec before any parsing begins.

Source

Thrown at compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/BinaryReplayCodec.java:1055

        }
        int size = encodedSize - 1;
        Map<String, String> properties = new EconomicHashMap<>();
        for (int i = 0; i < size; i++) {
            String key = requireNonNullString(readStringReference(in, state), "property key");
            String value = readStringReference(in, state);
            properties.put(key, value);
        }
        return properties;
    }

    private static void verifyHeader(ObjectCopierInputStream in) throws IOException {
        for (byte expected : MAGIC) {
            int actual = in.read();
            if (actual < 0) {
                throw new EOFException();
            }
            if (actual != Byte.toUnsignedInt(expected)) {
                throw new IOException("Invalid replay file header");
            }
        }
        int version = in.readPackedUnsignedInt();
        if (version != VERSION) {
            throw new IOException("Unsupported replay file version " + version);
        }
    }

    private static void writeBooleanFlag(ObjectCopierOutputStream out, boolean value) throws IOException {
        out.write(value ? 1 : 0);
    }

    private static boolean readBooleanFlag(ObjectCopierInputStream in) throws IOException {
        int value = in.read();
        if (value < 0) {
            throw new EOFException();
        }
        return switch (value) {

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Confirm the file was produced by the binary replay writer of the same codec
  2. Re-record the replay file if the recording run was interrupted (file may be empty or partial)
  3. Point the replay tool at the correct file path

Example fix

// before
try (var in = new ObjectCopierInputStream(fileIn)) {
    Object r = readValue(in, state);
}

// after
byte[] head = fileIn.readNBytes(MAGIC.length);
if (!Arrays.equals(head, MAGIC)) {
    throw new IOException("Not a binary replay file");
}
Defensive patterns

Strategy: validation

Validate before calling

static boolean hasValidMagic(java.io.InputStream in) throws IOException {
    in.mark(MAGIC.length);
    boolean ok = true;
    for (byte expected : MAGIC) {
        int b = in.read();
        ok &= b == Byte.toUnsignedInt(expected);
    }
    in.reset();
    return ok;
}

Try / catch

try {
    codec.readReplay(in);
} catch (IOException e) {
    if ("Invalid replay file header".equals(e.getMessage())) {
        // wrong file or wrong format: check the path and the recording flags used
    } else throw e;
}

Prevention

When it happens

Trigger: Feeding a text replay file (old replay format), an arbitrary binary, or an empty/truncated file to the binary replay reader; passing a file of a different codec's format.

Common situations: Mixing up old textual -XX:+ReplayCompiles output with the new binary format; wrong file passed on the command line; a zero-byte file from a crashed recording run.

Related errors


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