oracle/graal · error · ParserException.ClassFormatError
Invalid method signature: {}
Error message
Invalid method signature: {} What it means
SignatureSymbols.parse splits a method signature descriptor such as '(ILjava/lang/String;)V' into parameter and return types. The very first check requires length >= 3 and a leading '('; anything shorter or not starting with '(' throws ClassFormatError 'Invalid method signature: <sig>'.
Source
Thrown at espresso-shared/src/com.oracle.truffle.espresso.classfile/src/com/oracle/truffle/espresso/classfile/descriptors/SignatureSymbols.java:202
if (type == ParserTypes.java_lang_Object || TypeSymbols.isArray(type)) {
return ParserTypes.java_lang_Object;
} else if (type == ParserTypes._int || type == ParserTypes._short || type == ParserTypes._boolean || type == ParserTypes._char) {
return ParserTypes._int;
} else {
return type;
}
}
/**
* Parses a signature descriptor string into its parameter and return type components.
*
* @return the parsed parameter types followed by the return type.
* @throws ParserException.ClassFormatError if {the signature is not well-formed
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public static Symbol<Type>[] parse(TypeSymbols typeSymbols, Symbol<Signature> signature) throws ParserException.ClassFormatError {
if ((signature.length() < 3) || signature.byteAt(0) != '(') {
throw new ParserException.ClassFormatError("Invalid method signature: " + signature);
}
final List<Symbol<Type>> buf = new ArrayList<>();
int i = 1;
while (signature.byteAt(i) != ')') {
final Symbol<Type> descriptor = typeSymbols.parse(signature, i, true);
buf.add(descriptor);
i = i + descriptor.length();
if (i >= signature.length()) {
throw new ParserException.ClassFormatError("Invalid method signature: " + signature);
}
}
i++;
final Symbol<Type> descriptor = typeSymbols.parse(signature, i, true);
if (i + descriptor.length() != signature.length()) {
throw new ParserException.ClassFormatError("Invalid method signature: " + signature);
}
final Symbol<Type>[] descriptors = buf.toArray(new Symbol[buf.size() + 1]);
descriptors[buf.size()] = descriptor;View on GitHub (pinned to a66e9ccd1d)
Solutions
- Ensure the signature is a full method descriptor: starts with '(', ends with a return type, minimal valid form is '()V'
- If you hold a field descriptor, wrap or re-fetch the method descriptor rather than reusing the field type
- Add a cheap pre-check: sig.length() >= 3 && sig.charAt(0) == '(' before parsing
Example fix
// before Symbol<Type>[] parts = SignatureSymbols.parse(types, fieldDescriptor); // e.g. "I" // after Symbol<Type>[] parts = SignatureSymbols.parse(types, methodDescriptor); // e.g. "(I)V"
Defensive patterns
Strategy: validation
Validate before calling
if (sig.length() < 3 || sig.charAt(0) != '(') throw new IllegalArgumentException("Not a method signature: " + sig); Type guard
static boolean looksLikeMethodSignature(String s) { return s != null && s.length() >= 3 && s.charAt(0) == '(' && s.indexOf(')') > 0; } Try / catch
catch (ParserException.ClassFormatError e) { report the offending signature and where it came from (class/method) } Prevention
- Do not reuse field descriptors where method signatures are expected
- Fuzz-test generated signatures through a parser in CI
When it happens
Trigger: Passing a signature like 'V', '()', '(I', or a field descriptor by mistake (e.g. 'I' or 'Ljava/lang/String;') where a method signature is required; truncated signature strings from generated bytecode.
Common situations: Using a field type descriptor where the method signature slot is expected (common in generated-proxies/serialization code); empty signature from a failed lookup; off-by-one string slicing when concatenating descriptors.
Related errors
- unknown primitive or void type character:
- Unsupported java version: {} ({})
- invalid descriptor: {}
- invalid type descriptor: {}
- Invalid Java name {}
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/e70d31430f1a497b.
Report an issue: GitHub.