oracle/graal · error · IllegalArgumentException
${input} is not an instance of a registered class.
Error message
${input} is not an instance of a registered class. What it means
Thrown by RecordingCompilationProxies.proxify when replay-compilation recording is asked to wrap an object whose class was never registered in CompilerInterfaceDeclarations. The recording machinery can only intercept calls on interfaces it knows how to proxy; an unregistered concrete class cannot be proxied, so it fails fast with IllegalArgumentException instead of silently recording nothing.
Source
Thrown at compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordingCompilationProxies.java:171
@Override
public Platform targetPlatform() {
return Platform.ofCurrentHost();
}
@Override
public DebugCloseable withDebugContext(DebugContext debugContext) {
return DebugCloseable.VOID_CLOSEABLE;
}
@Override
public CompilationProxy proxify(Object input) {
if (input instanceof CompilationProxy compilationProxy) {
return compilationProxy;
}
CompilerInterfaceDeclarations.Registration registration = declarations.findRegistrationForInstance(input);
if (registration == null) {
throw new IllegalArgumentException(input + " is not an instance of a registered class.");
}
return CompilationProxy.newProxyInstance(registration.clazz(), (proxy, method, callback, args) -> {
if (method.equals(CompilationProxyBase.unproxifyMethod)) {
return input;
}
Object[] unproxifiedArgs = (Object[]) unproxifyRecursive(args);
CompilerInterfaceDeclarations.MethodStrategy methodStrategy = registration.findStrategy(method);
OperationRecorder.RecordedOperationKey key = new OperationRecorder.RecordedOperationKey(input, method, unproxifiedArgs);
Object result;
if (methodStrategy == CompilerInterfaceDeclarations.MethodStrategy.RecordReplay) {
Object resultOrMarker = recorder.getRecordedResultOrMarker(key);
if (resultOrMarker instanceof SpecialResultMarker.ExceptionThrownMarker exceptionThrownMarker) {
throw (Throwable) proxifyRecursive(exceptionThrownMarker.getThrown());
} else if (resultOrMarker == SpecialResultMarker.NULL_RESULT_MARKER) {
return null;
} else if (resultOrMarker != SpecialResultMarker.NO_RESULT_MARKER) {
return proxifyRecursive(resultOrMarker);
}View on GitHub (pinned to a66e9ccd1d)
Solutions
- Register the object's class/interface in CompilerInterfaceDeclarations so findRegistrationForInstance returns non-null, then retry the recording.
- If the object should pass through unproxied, check it for CompilationProxy before calling proxify or route it outside the proxy layer.
- Update to a GraalVM version where the class is registered (if the class comes from a newer compiler-interface change).
Example fix
// before
Object proxy = recordingProxies.proxify(newObject);
// after
CompilerInterfaceDeclarations.Registration reg = declarations.findRegistrationForInstance(newObject);
if (reg == null) {
// register newObject's interface in CompilerInterfaceDeclarations first
throw new IllegalStateException("Register " + newObject.getClass() + " before recording");
}
Object proxy = recordingProxies.proxify(newObject); Defensive patterns
Strategy: validation
Validate before calling
// before proxify, confirm the instance is registrable
Object input = /* ... */;
if (!(input instanceof CompilationProxy) &&
declarations.findRegistrationForInstance(input) == null) {
// do not call proxify; register the class or pass the raw object
throw new IllegalStateException("Unregistered class for recording: " + input.getClass());
}
CompilationProxy proxy = recordingProxies.proxify(input); Prevention
- Register every compiler-interface implementation class in CompilerInterfaceDeclarations before enabling recording.
- Keep recording and compiler-interface changes in the same change set so new classes never bypass registration.
When it happens
Trigger: Calling RecordingCompilationProxies.proxify(Object) with an input that is neither already a CompilationProxy nor an instance of a class registered via CompilerInterfaceDeclarations registration lookup (declarations.findRegistrationForInstance(input) returns null). Typically happens when a new type flows through the compiler interface during -Dgraal.ReplayCompilation recording but its interface was not added to the registered declarations.
Common situations: Extending the compiler-interface surface (adding a new implementation class of jdk.vm.ci or Graal interface types) without registering it in CompilerInterfaceDeclarations; version mismatches where a replay/recording branch added a class the declarations table does not know; recording a compilation that touches a rarely used VM-CI implementation class.
Related errors
- No serializer for :
- Unknown registration
- Method ${methodName} not found
- Unexpected marker
- Unknown enum constant for
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/06ae0b81c17e9ed5.
Report an issue: GitHub.