quarkusio/quarkus · error · IllegalArgumentException
Invalid type variable in signature: ${signature} at position
Error message
Invalid type variable in signature: ${signature} at position ${i} What it means
TypeSignatureParser parses JVM field/method type signature strings (e.g. 'Ljava/util/List<Ljava/lang/String;>;'). Type variable signatures ('T...;') are deliberately unsupported because java.lang.reflect.TypeVariable requires the GenericDeclaration context, which is absent from the raw signature. Hitting 'T' in parseType throws this IllegalArgumentException naming the signature and position.
Source
Thrown at independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/util/types/TypeSignatureParser.java:60
break LOOP;
case 'S':
ret = short.class;
break LOOP;
case 'Z':
ret = boolean.class;
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() + ";");View on GitHub (pinned to e1c734241f)
Solutions
- Replace type variables with concrete types: specialize the class/method (e.g. use a subclass with concrete type arguments instead of raw generic ones)
- Resolve the TypeVariable manually against the declaring GenericDeclaration before parsing
- Pre-process the signature to substitute 'TName;' with the erased or actual type before calling the parser
- Avoid parsing signatures of raw generic members; operate on ParameterizedType from a concrete subclass via getGenericSuperclass
Example fix
// before
TypeSignatureParser.parse("(TT;)TT;"); // throws
// after
class StringResource extends GenericResource<String> {}
Type t = StringResource.class.getGenericSuperclass(); // concrete ParameterizedType Defensive patterns
Strategy: try-catch
Validate before calling
static boolean signatureHasTypeVariable(String sig) {
return sig != null && sig.contains("T") && Pattern.compile("(^|[^A-Z])T[A-Za-z0-9_$]*;").matcher(sig).find();
}
// reject/guard before calling TypeSignatureParser.parse Try / catch
try {
Type t = TypeSignatureParser.parse(signature);
} catch (IllegalArgumentException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Invalid type variable")) {
throw new UnsupportedOperationException("Resolve type variables against a concrete subclass first");
} else throw e;
} Prevention
- Avoid parsing signatures of raw generic members; specialize with concrete type arguments first
- Resolve TypeVariables via getGenericSuperclass on a concrete subclass before signature work
- Document that the signature parser does not support 'T...;' tokens
- Filter out methods/fields referencing type parameters before introspection
When it happens
Trigger: Parsing a signature string containing a type variable reference, e.g. from a generic class method like '(TT;)TT;' or a field 'TT;', passed to TypeSignatureParser.parse or parseReference->parseType.
Common situations: Reflecting on generic classes whose members reference the class's own type parameters; generating signatures from generic code and feeding them to RESTEasy Reactive type introspection (e.g. generic resource classes or MessageBodyReader resolution).
Related errors
- Invalid signature char: ${c} in ${signature} at position ${i
- 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/746e1225163154b5.
Report an issue: GitHub.