oracle/graal · error · IllegalStateException

Unexpected value: ${registerConfig}

Error message

Unexpected value: ${registerConfig}

What it means

RegisterConfigSerializer.serialize maps a live RegisterConfig instance to a tag string by instanceof-pattern match over AMD64HotSpotRegisterConfig, RISCV64HotSpotRegisterConfig, and AArch64HotSpotRegisterConfig. Any other RegisterConfig implementation (custom subclass, new backend) hits IllegalStateException('Unexpected value: ...').

Source

Thrown at compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/JsonReplayCodec.java:1677

        @Override
        public Class<?> clazz() {
            return RegisterConfig.class;
        }

        @Override
        public String tag() {
            return "registerConfig";
        }

        @Override
        public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException {
            RegisterConfig registerConfig = (RegisterConfig) instance;
            String name = switch (registerConfig) {
                case AMD64HotSpotRegisterConfig ignored -> "AMD64";
                case RISCV64HotSpotRegisterConfig ignored -> "RISCV64";
                case AArch64HotSpotRegisterConfig ignored -> "AArch64";
                default -> throw new IllegalStateException("Unexpected value: " + registerConfig);
            };
            objectBuilder.append("name", name);
            serializer.serialize(hostTarget, objectBuilder.append("target"));
            serializer.serialize(registerConfig.getAllocatableRegisters(), objectBuilder.append("allocatable"));
            objectBuilder.append("windowsOS", isHostWindowsOS);
        }

        @Override
        @SuppressWarnings("unchecked")
        public Object deserialize(EconomicMap<String, Object> json, RecursiveDeserializer deserializer, CompilationProxies.ProxyFactory proxyFactory) throws DeserializationException {
            String name = (String) json.get("name");
            TargetDescription targetDescription = (TargetDescription) deserializer.deserialize(json.get("target"), proxyFactory);
            List<Register> allocatable = (List<Register>) deserializer.deserialize(json.get("allocatable"), proxyFactory);
            switch (name) {
                case "AMD64" -> {
                    boolean windowsOS = (boolean) json.get("windowsOS");
                    return new AMD64HotSpotRegisterConfig(targetDescription, allocatable, windowsOS);
                }

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Identify the actual class from the message and add a matching case + name to serialize() and a mirror case in deserialize()
  2. Avoid wrapping register configs in decorators when replay recording is enabled
  3. Record/replay on matching builds
Defensive patterns

Strategy: type-guard

Type guard

static boolean isSupportedRegisterConfig(RegisterConfig rc) {
    return rc instanceof AMD64HotSpotRegisterConfig
        || rc instanceof RISCV64HotSpotRegisterConfig
        || rc instanceof AArch64HotSpotRegisterConfig;
}

Prevention

When it happens

Trigger: Serializing a replay on a JVM whose HotSpot register config is a class outside the three known ones — custom backend, a new port, or a config wrapper/decorator class introduced by a newer version.

Common situations: Forked GraalVM with an extra architecture; version drift adding a new register-config class; wrapping configs in delegates for testing.

Related errors


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