oracle/graal · error · DeserializationException

Invalid constant.

Error message

Invalid constant.

What it means

EnumSerializer.deserialize resolves an enum constant by name: it loads the enum class (from the 'holder' entry) and scans getEnumConstants() for one whose name() equals the recorded 'constant'. If no constant matches, it throws DeserializationException('Invalid constant.') — the enum exists but the name does not.

Source

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

        @Override
        public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException {
            Enum<?> en = (Enum<?>) instance;
            serializer.serialize(en.getClass(), objectBuilder.append("holder"));
            objectBuilder.append("constant", en.name());
        }

        @SuppressWarnings("unchecked")
        @Override
        public Object deserialize(EconomicMap<String, Object> json, RecursiveDeserializer deserializer, CompilationProxies.ProxyFactory proxyFactory) throws DeserializationException {
            Class<? extends Enum<?>> enumClass = (Class<? extends Enum<?>>) deserializer.deserialize(json.get("holder"), proxyFactory);
            String constantName = (String) json.get("constant");
            for (Enum<?> constant : enumClass.getEnumConstants()) {
                if (constant.name().equals(constantName)) {
                    return constant;
                }
            }
            throw new DeserializationException(this, json, "Invalid constant.");
        }
    }

    private static final class ArraySerializer implements ObjectSerializer {

        private final CompilerInterfaceDeclarations declarations;

        private ArraySerializer(CompilerInterfaceDeclarations declarations) {
            this.declarations = declarations;
        }

        @Override
        public boolean serializesSubclasses() {
            return true;
        }

        @Override
        public Class<?> clazz() {

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Use identical GraalVM builds for record and replay
  2. Inspect the entry's 'holder' and 'constant' fields (included in the DeserializationException context) and map the old name to the new one
  3. If replaying across versions is required, add a name-alias mapping in EnumSerializer before throwing
Defensive patterns

Strategy: validation

Validate before calling

// Pre-check the constant name against the enum before full replay
Class<? extends Enum<?>> ec = loadEnumClass(holderName);
boolean ok = Arrays.stream(ec.getEnumConstants()).anyMatch(c -> c.name().equals(constantName));
if (!ok) throw new IllegalArgumentException("Enum " + holderName + " has no constant " + constantName);

Prevention

When it happens

Trigger: Deserializing an enum entry where 'constant' names a value absent from the loaded enum class: enum constant renamed/removed between the recording and replaying GraalVM builds, or a typo in hand-edited JSON.

Common situations: Version skew where CPUFeature or phase enums gained/renamed constants; replaying across CPU generations where a CPUFeature enum differs; manual JSON edits.

Related errors


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