quarkusio/quarkus · error · IllegalArgumentException
Invalid signature char: ${c} in ${signature} at position ${i
Error message
Invalid signature char: ${c} in ${signature} at position ${i} What it means
TypeSignatureParser.parseType iterates over signature characters and only recognizes valid type-signature tokens (object types 'L...;', arrays '[', primitives like 'I', 'Z', etc.). Any other character reaches the default branch and throws this IllegalArgumentException identifying the bad char, the full signature, and the position.
Source
Thrown at independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/util/types/TypeSignatureParser.java:66
break LOOP;
case 'V':
ret = void.class;
break LOOP;
// ClassTypeSignature
case 'L':
ret = parseReference();
break LOOP;
// TypeVariableSignature
case 'T':
// Stef has come to the conclusion that because TypeVariable depends on the GenericDeclaration that defined them, which is lacking
// in signatures unless we have access to the current context, we should not support them
throw new IllegalArgumentException(
"Invalid type variable in signature: " + new String(chars) + " at position " + i);
case '[':
arrayCount++;
break;
default:
throw new IllegalArgumentException(
"Invalid signature char: " + c + " in " + new String(chars) + " at position " + i);
}
} while (true);
if (arrayCount > 0) {
if (ret instanceof Class) {
Class<?> retClass = (Class<?>) ret;
if (retClass.isPrimitive()) {
// load [I or [[I
return loadClass(new String(chars, start, i - start));
}
// get the [L part and the name out of the class
return loadClass(new String(chars, start, arrayCount + 1) + retClass.getName() + ";");
}
if (ret instanceof ParameterizedType) {
// this is a moronic API
for (int a = 0; a < arrayCount; a++) {
ret = new GenericArrayTypeImpl(ret);
}View on GitHub (pinned to e1c734241f)
Solutions
- Verify the signature is a complete, valid JVM type signature (object types must end with ';')
- Print the full signature and check the reported position for the offending character
- Regenerate the signature instead of hand-crafting it (e.g. from Class.getName()/descriptor APIs)
- Guard the parse call with try-catch and log the signature for diagnosis
Example fix
// before
TypeSignatureParser.parse("Ljava/util/List");
// after
TypeSignatureParser.parse("Ljava/util/List<Ljava/lang/String;>;"); Defensive patterns
Strategy: try-catch
Validate before calling
static boolean looksLikeTypeSignature(String s) {
return s != null && !s.isEmpty()
&& (s.startsWith("L") && s.endsWith(";") || s.startsWith("[") || "BCDFIJSZV".indexOf(s.charAt(0)) >= 0);
} Try / catch
try {
Type t = TypeSignatureParser.parse(signature);
} catch (IllegalArgumentException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Invalid signature char")) {
log.error("Bad signature: " + e.getMessage());
return null; // or re-generate the signature
} else throw e;
} Prevention
- Generate signatures programmatically instead of hand-writing them
- Verify object types terminate with ';' and primitives use valid descriptors
- Keep signatures intact in storage/transport — watch for truncation
- Log the full signature (the error includes it) to spot the offending char quickly
When it happens
Trigger: Calling TypeSignatureParser.parse with a malformed or truncated signature string, e.g. "Ljava/util/List" missing the terminating ';', "X" as a type, or a corrupted string built manually.
Common situations: Hand-written or programmatically truncated descriptor strings; signatures copied from bytecode dumps with offsets off by one; storing signatures in config/DB and losing characters.
Related errors
- Invalid type variable in signature: ${signature} at position
- Type has no raw type class:
- Type is not parameterized:
- Not a valid type:
- Unable to find type arguments of ${interfaceToFind}
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/826300b3dd8162b8.
Report an issue: GitHub.