oracle/graal · error · IllegalArgumentException
Signature must start with a '(':
Error message
Signature must start with a '(': What it means
IllegalArgumentException from SignatureUtil.parseSignatureInternal: the descriptor does not start with '(' — the mandatory opening parenthesis of a JVMS 4.3.3 method descriptor. SignatureUtil only accepts full method descriptors '(params)return', so a bare type descriptor such as 'I' or 'Ljava/lang/String;' (valid as a field descriptor, not a method descriptor) is rejected.
Source
Thrown at compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/util/SignatureUtil.java:141
}
}
/**
* Checks if the given signature can be successfully parsed by
* {@link #parseSignature(String, List)}.
*
* @param signature the signature to check
* @param acceptMissingReturnType whether a signature without a return type is considered to be
* valid
* @return whether the signature can be successfully parsed
*/
public static boolean isSignatureValid(String signature, boolean acceptMissingReturnType) {
return parseSignatureInternal(signature, null, false, acceptMissingReturnType) != null;
}
private static <T> T throwOrReturn(boolean shouldThrow, T returnValue, String errorMessage) {
if (shouldThrow) {
throw new IllegalArgumentException(errorMessage);
} else {
return returnValue;
}
}
}
View on GitHub (pinned to a66e9ccd1d)
Solutions
- Wrap the value as a method descriptor if it is meant to be a parameter/return type: '(I)V' not 'I'.
- If you have a Java-source signature, convert it with a proper parser (e.g. MetaAccessProvider.parseMethodDescriptor or bytecode-tooling helpers) instead of string surgery.
- Pre-check with SignatureUtil.isSignatureValid(sig, false) on untrusted input.
Example fix
// before
String ret = SignatureUtil.parseSignature("I", params);
// after
String ret = SignatureUtil.parseSignature("(I)V", params); // full method descriptor Defensive patterns
Strategy: validation
Validate before calling
if (sig == null || sig.isEmpty() || sig.charAt(0) != '(') {
throw new IllegalArgumentException("expected method descriptor like (I)V, got: " + sig);
} Type guard
static boolean isMethodDescriptor(String s) {
return s != null && !s.isEmpty() && s.charAt(0) == '(' && s.indexOf(')') > 0;
} Try / catch
try {
SignatureUtil.parseSignature(sig, params);
} catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("Signature must start")) {
sig = "(" + sig + ")V"; // only if you knowingly held a bare type descriptor
} else throw e;
} Prevention
- Remember SignatureUtil accepts only full method descriptors, not field-type descriptors.
- Wrap bare type descriptors explicitly when building a synthetic method signature.
- Pre-validate externally sourced strings with isSignatureValid.
When it happens
Trigger: Calling SignatureUtil.parseSignature with a field-type descriptor ('I', 'Ljava/lang/String;'), a human-readable signature ('void foo(int)'), or a string that lost its leading '(' in preprocessing.
Common situations: Confusing field descriptors with method descriptors when reading class-file metadata; passing a Java-source-style signature where a bytecode descriptor is required; off-by-one substring that drops the first character.
Related errors
- Signature cannot be empty
- Extra characters at end of signature:
- Class name in signature contains '.' at index
- Invalid character '
- Truncated signature:
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/376632b4b4d63020.
Report an issue: GitHub.