{"record":{"id":"0eaff680aabf9f4c","repo":"quarkusio/quarkus","slug":"unsupported-wildcard-type-wildcard","errorCode":null,"errorMessage":"Unsupported wildcard type: ${wildcard}","messagePattern":"Unsupported wildcard type: (.+?)","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"core/deployment/src/main/java/io/quarkus/deployment/recording/BytecodeRecorderImpl.java","lineNumber":843,"sourceCode":"                    @Override\n                    ResultHandle doLoad(MethodContext context, MethodCreator method, ResultHandle array) {\n                        return method.invokeStaticMethod(ofMethod(WildcardTypeImpl.class, \"withUpperBound\",\n                                WildcardType.class, java.lang.reflect.Type.class), context.loadDeferred(res));\n                    }\n                };\n            } else if (lowerBound.length == 1) {\n                // lower bound\n                DeferredParameter res = loadObjectInstance(lowerBound[0], existing,\n                        java.lang.reflect.Type.class, relaxedValidation);\n                return new DeferredParameter() {\n                    @Override\n                    ResultHandle doLoad(MethodContext context, MethodCreator method, ResultHandle array) {\n                        return method.invokeStaticMethod(ofMethod(WildcardTypeImpl.class, \"withLowerBound\",\n                                WildcardType.class, java.lang.reflect.Type.class), context.loadDeferred(res));\n                    }\n                };\n            } else {\n                throw new UnsupportedOperationException(\"Unsupported wildcard type: \" + wildcard);\n            }\n        } else if (expectedType == boolean.class || expectedType == Boolean.class || param instanceof Boolean) {\n            return new DeferredParameter() {\n                @Override\n                ResultHandle doLoad(MethodContext context, MethodCreator method, ResultHandle array) {\n                    return method.load((boolean) param);\n                }\n            };\n        } else if (expectedType == int.class || expectedType == Integer.class || param instanceof Integer) {\n            return new DeferredParameter() {\n                @Override\n                ResultHandle doLoad(MethodContext context, MethodCreator method, ResultHandle array) {\n                    return method.load((int) param);\n                }\n            };\n        } else if (expectedType == short.class || expectedType == Short.class || param instanceof Short) {\n            return new DeferredParameter() {\n                @Override","sourceCodeStart":825,"sourceCodeEnd":861,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/core/deployment/src/main/java/io/quarkus/deployment/recording/BytecodeRecorderImpl.java#L825-L861","documentation":"When recording a java.lang.reflect.WildcardType parameter, Quarkus can emit lower-bounded wildcards (? super X); if the wildcard has no lower bound in the branch being handled (e.g. only an upper bound '? extends X' is unsupported here), it throws UnsupportedOperationException. This is a limitation of the recorder's type-parameter recording support.","triggerScenarios":"Passing a reflectively-obtained Type that is a WildcardType with an upper bound only (e.g. '? extends Foo'), or an unbounded '?' not covered by the handled cases, into a recorder method parameter of type Type.","commonSituations":"Extension code passing generic reflection metadata (from ParameterizedType fields or generated config mappings) into recorders; using types captured from user classes with '? extends' bounds.","solutions":["Avoid passing raw WildcardType objects to recorders; resolve the wildcard to its concrete upper bound (e.g. via quarkus-extension's ReflectUtil or GAST types) before recording","Use parameterized Class/TypeToken-style concrete types instead of wildcards","Check Quarkus version — support for wildcard bounds has changed; upgrade to a version handling your wildcard shape","If you control the type source, replace '? extends X' declarations with the concrete type X","File an issue if your wildcard type should be supported (lower-bound wildcards are handled)"],"exampleFix":"// before\nType t = field.getGenericType(); // contains '? extends Foo'\nrecorder.setType(t);\n// after\nType t = resolveWildcardToUpperBound(field.getGenericType()); // yields Foo.class\nrecorder.setType(t);","handlingStrategy":"type-guard","validationCode":"static boolean isRecorderSafeType(java.lang.reflect.Type t) {\n    if (t instanceof java.lang.reflect.WildcardType w) {\n        return w.getLowerBounds().length > 0; // only lower-bounded wildcards are supported\n    }\n    return true;\n}","typeGuard":"static boolean isWildcardWithLowerBound(java.lang.reflect.Type t) {\n    return t instanceof java.lang.reflect.WildcardType w && w.getLowerBounds().length > 0;\n}","tryCatchPattern":"try {\n    recorder.setType(genericType);\n} catch (UnsupportedOperationException e) {\n    if (e.getMessage().startsWith(\"Unsupported wildcard\")) {\n        recorder.setType(resolveToUpperBound(genericType));\n    } else { throw e; }\n}","preventionTips":["Resolve wildcards to concrete upper-bound types before recording","Avoid '? extends' bounds in types that cross the recorder boundary","Pin/upgrade Quarkus versions deliberately — wildcard support evolves"],"tags":["quarkus","generics","wildcard","recorder","build-time"],"backgroundTag":"unsupported-generic-type","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}