oracle/graal · error · NoSuchMethodException
%s %s.%s(%s)
Error message
%s %s.%s(%s)
What it means
A NoSuchMethodException whose message is a full method signature ('returnType holder.name(argTypes)'), thrown from readMethodNameAndTypes after reflection over the deserialized holder class found no method matching the recorded name, parameter types, and return type. The serializer stores enough type information to relocate the exact Method, so this fires when the class on the reading side no longer has that exact method — a binary-compatibility break between the writing and reading runtimes.
Source
Thrown at espresso/src/org.graalvm.continuations/src/org/graalvm/continuations/FrameRecordSerializer.java:317
Class<?>[] argTypes = new Class<?>[numArgs];
for (int i = 0; i < numArgs; i++) {
argTypes[i] = readClass(classLoader);
}
for (Method method : declaringClass.getDeclaredMethods()) {
if (!method.getName().equals(name)) {
continue;
}
if (!Arrays.equals(method.getParameterTypes(), argTypes)) {
continue;
}
if (!method.getReturnType().equals(returnType)) {
continue;
}
return method;
}
throw new NoSuchMethodException("%s %s.%s(%s)".formatted(
returnType.getName(), declaringClass.getName(), name, String.join(", ", Arrays.stream(argTypes).map(Class::getName).toList())));
}
private Class<?> readClass(ClassLoader classLoader) throws IOException, ClassNotFoundException {
assert in != null;
int kind = in.readUnsignedByte();
return switch (kind) {
case 'I' -> int.class;
case 'Z' -> boolean.class;
case 'D' -> double.class;
case 'F' -> float.class;
case 'J' -> long.class;
case 'B' -> byte.class;
case 'C' -> char.class;
case 'S' -> short.class;
case 'V' -> void.class;
case 'L' -> Class.forName(readString(), false, classLoader);
default -> throw new IOException("Unexpected kind: " + kind);View on GitHub (pinned to a66e9ccd1d)
Solutions
- Restore binary compatibility for the method named in the exception (same name, parameter types, return type) on the reading side, then retry deserialize.
- If the method legitimately changed, drain or discard in-flight continuations before deploying (do not migrate across incompatible builds).
- Keep the exact signature in mind: return type participates in the match — a covariant change alone breaks it.
- Include continuation-payload compatibility in your deployment checklist: any method on a suspendable stack is now a serialization contract.
Example fix
// before
// v1 stack: com.acme.Task.run(Request) -> void; v2 deployed with run(Request, Context)
Continuation.deserialize(v1Payload, loader); // NoSuchMethodException: void com.acme.Task.run(com.acme.Request)
// after
// v2 keeps the old signature and overloads instead
public void run(Request req) { run(req, defaultContext()); }
public void run(Request req, Context c) { ... } Defensive patterns
Strategy: validation
Validate before calling
// before resume, verify the exact method still exists
Class<?> holder = Class.forName(frameHolderName, false, loader);
for (Method m : holder.getDeclaredMethods()) {
if (m.getName().equals(recordedName) && Arrays.equals(m.getParameterTypes(), recordedArgs)
&& m.getReturnType() == recordedReturn) { return; } // compatible
}
throw new IllegalStateException("Incompatible deployment: " + recordedSignature + " missing"); Try / catch
try { Continuation.deserialize(bytes, loader); } catch (IOException e) { if (e.getCause() instanceof NoSuchMethodException nsme) { /* binary-incompatible build: drain in-flight continuations before deploy */ } } Prevention
- Keep the exact signatures (name, params, return type) of suspendable-stack methods stable across releases.
- Drain or expire persisted continuations before deploying incompatible builds.
- Remember return type participates in the method match — covariant changes break deserialization.
When it happens
Trigger: Serializing a continuation with method M(int)→String on the stack, deploying a new build where M was renamed, gained/lost parameters, changed return type, or moved to a superclass, then deserializing the old payload.
Common situations: Rolling deployments where in-flight continuations are migrated between versions; refactoring (rename method, change signature) while persisted continuations still reference the old shape; different compiler generating bridge/synthetic methods on one side only.
Related errors
- You can't resume a continuation while it is being serialized
- You cannot serialize a continuation whilst it's running, as
- This VM does not support continuations.
- Unsupported serialized continuation version: %s\nCurrent sup
- Illegal serialized continuation is in running state.
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/05acb0eace94e6b0.
Report an issue: GitHub.