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

  1. Replace type variables with concrete types: specialize the class/method (e.g. use a subclass with concrete type arguments instead of raw generic ones)
  2. Resolve the TypeVariable manually against the declaring GenericDeclaration before parsing
  3. Pre-process the signature to substitute 'TName;' with the erased or actual type before calling the parser
  4. 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

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


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/746e1225163154b5. Report an issue: GitHub.