oracle/graal · error · IOException

Registration is not a singleton

Error message

Registration  is not a singleton

What it means

IOException thrown by BinaryReplayCodec.ReadState.singletonProxy when the stream requests a singleton proxy for a registration whose Registration is not marked singleton. The decoder distinguishes singleton types (one shared proxy) from instance types (per-id proxies); a non-singleton registration at a singleton reference site means the stream's shape disagrees with the current declarations — corruption or version mismatch.

Source

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

        private void defineMethod(int index, CompilationProxy.SymbolicMethod method) throws IOException {
            if (index != methodTable.size()) {
                throw new IOException("Invalid replay symbolic method definition index " + index);
            }
            methodTable.add(method);
        }

        private CompilerInterfaceDeclarations.Registration registrationAt(int index) throws IOException {
            if (index < 0 || index >= registrations.length) {
                throw new IOException("Invalid replay registration index " + index);
            }
            return registrations[index];
        }

        private Object singletonProxy(int registrationIndex) throws IOException {
            CompilerInterfaceDeclarations.Registration registration = registrationAt(registrationIndex);
            if (!registration.singleton()) {
                throw new IOException("Registration " + registration.clazz().getName() + " is not a singleton");
            }
            Object proxy = singletonProxies[registrationIndex];
            if (proxy == null) {
                proxy = proxyFactory.createProxy(registration);
                singletonProxies[registrationIndex] = proxy;
            }
            return proxy;
        }

        private Object instanceProxy(int registrationIndex, int id) throws IOException {
            CompilerInterfaceDeclarations.Registration registration = registrationAt(registrationIndex);
            if (registration.singleton()) {
                throw new IOException("Registration " + registration.clazz().getName() + " is a singleton");
            }
            EconomicMap<Integer, Object> proxies = instanceProxies[registrationIndex];
            if (proxies == null) {
                proxies = EconomicMap.create();
                instanceProxies[registrationIndex] = proxies;

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Regenerate the replay file with the same compiler build used for replay.
  2. Verify the file's integrity and retry.
  3. Treat replay data as build-local: never share across revisions.
Defensive patterns

Strategy: validation

Try / catch

try {
    replayCodec.decode(input);
} catch (IOException e) {
    if (e.getMessage().contains("is not a singleton")) {
        // singleton markings differ between builds: regenerate replay data
    }
    throw e;
}

Prevention

When it happens

Trigger: A SINGLETON_PROXY record indexes a registration whose singleton() flag is false in the running build — e.g. the producing build treated the type as a singleton while the consumer does not, or bytes were shuffled.

Common situations: Cross-build replay after compiler-interface annotations changed (singleton added/removed); corrupted replay artifacts.

Related errors


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