oracle/graal · error · IOException

Invalid replay string table index

Error message

Invalid replay string table index 

What it means

IOException thrown by BinaryReplayCodec.ReadState.stringAt when a replay data stream references a string table index that is negative or >= the current table size. The binary replay format resolves strings by index into a table built incrementally during decoding; an out-of-range index means the stream is corrupt, truncated, or was written by an incompatible codec version.

Source

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

    private final class ReadState {
        private final CompilationProxies.ProxyFactory proxyFactory;
        private final ArrayList<String> stringTable = new ArrayList<>();
        private final ArrayList<CompilationProxy.SymbolicMethod> methodTable = new ArrayList<>();
        private final Object[] singletonProxies = new Object[registrations.length];

        @SuppressWarnings("unchecked") private final EconomicMap<Integer, Object>[] instanceProxies = (EconomicMap<Integer, Object>[]) new EconomicMap<?, ?>[registrations.length];

        private Architecture architecture = hostTarget.arch;

        private ReadState(CompilationProxies.ProxyFactory proxyFactory) {
            this.proxyFactory = proxyFactory;
            stringTable.add(null);
        }

        private String stringAt(int index) throws IOException {
            if (index < 0 || index >= stringTable.size()) {
                throw new IOException("Invalid replay string table index " + index);
            }
            return stringTable.get(index);
        }

        private void defineString(int index, String value) throws IOException {
            if (index != stringTable.size()) {
                throw new IOException("Invalid replay string definition index " + index);
            }
            stringTable.add(value);
        }

        private CompilationProxy.SymbolicMethod methodAt(int index) throws IOException {
            if (index < 0 || index >= methodTable.size()) {
                throw new IOException("Invalid replay symbolic method index " + index);
            }
            return methodTable.get(index);
        }

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Regenerate the replay file with the exact compiler build used for replay.
  2. Verify the file is complete and unmodified (checksum/re-copy) and retry.
  3. If you must replay across versions, re-record profiles on the current build instead of reusing old ones.
Defensive patterns

Strategy: validation

Validate before calling

// Validate replay file before use: writer header/version must match reader build, and file must be complete
Path p = Paths.get(replayFile);
long expected = Long.parseLong(Files.readString(p.resolveSibling(p.getFileName() + ".size"))); // emitted by capture tooling
if (Files.size(p) != expected) {
    throw new IOException("Replay file truncated: " + p);
}

Try / catch

try {
    replayCodec.decode(input);
} catch (IOException e) {
    if (e.getMessage().startsWith("Invalid replay string table index")) {
        // regenerate the replay file on this build; do not retry the same bytes
    }
    throw e;
}

Prevention

When it happens

Trigger: Reading a replay file (-Dgraal.ReplayCompilation / replay tooling) where a record refers to a string index not yet defined (or beyond EOF), or the file was produced by a compiler whose BinaryReplayCodec wrote a different table layout.

Common situations: Replaying compilation profiles across compiler builds (table order changed); truncated file transfers; bit rot in stored .glog/replay artifacts; hand-editing replay files.

Related errors


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