{"record":{"id":"e6776e3a3f0c672d","repo":"json-path/JsonPath","slug":"no-type-info-in-typeref","errorCode":null,"errorMessage":"No type info in TypeRef","messagePattern":"No type info in TypeRef","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"json-path/src/main/java/com/jayway/jsonpath/TypeRef.java","lineNumber":37,"sourceCode":"\n\n/**\n * Used to specify generic type information in {@link com.jayway.jsonpath.ReadContext}\n *\n * <code>\n *       TypeRef ref = new TypeRef<List<Integer>>() { };\n * </code>\n *\n * @param <T>\n */\npublic abstract class TypeRef<T> implements Comparable<TypeRef<T>> {\n    protected final Type type;\n    \n    protected TypeRef()\n    {\n        Type superClass = getClass().getGenericSuperclass();\n        if (superClass instanceof Class<?>) {\n            throw new IllegalArgumentException(\"No type info in TypeRef\");\n        }\n        type = ((ParameterizedType) superClass).getActualTypeArguments()[0];\n    }\n\n    public Type getType() { return type; }\n    \n    /**\n     * The only reason we define this method (and require implementation\n     * of <code>Comparable</code>) is to prevent constructing a\n     * reference without type information.\n     */\n    @Override\n    public int compareTo(TypeRef<T> o) {\n        return 0;\n    }\n}\n\n","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/json-path/JsonPath/blob/62a4c9f0f65ba3f625aa0867d64c528ba72d09ec/json-path/src/main/java/com/jayway/jsonpath/TypeRef.java#L19-L55","documentation":"TypeRef<T> captures a generic type via a superclass reflection trick that only works when the subclass supplies actual type arguments. Instantiating the raw TypeRef (or new TypeRef() {} with no parameterization) makes getGenericSuperclass() return the plain Class TypeRef, and an IllegalArgumentException 'No type info in TypeRef' is thrown from the constructor.","triggerScenarios":"new TypeRef() {} or new TypeRef() — anonymous/inline subclass without a type parameter, e.g. passing it to JsonPath.parse(...).read(\"$\", new TypeRef(){}) instead of new TypeRef<List<Map<String,Object>>>(){}.","commonSituations":"Migrating from Class-based reads to TypeRef-based generic reads and forgetting the diamond/type argument; IDE auto-completing 'new TypeRef(){}' without filling in the type.","solutions":["Always subclass with an explicit type argument: new TypeRef<List<String>>() {}.","If the target type is a simple class, pass the Class directly (read(path, Class)) instead of TypeRef.","Add a compile-time check or unit test exercising the TypeRef read so raw usage fails fast in review."],"exampleFix":"// before\nList<Map<String, Object>> list = doc.read(\"$.items\", new TypeRef() {});\n// after\nList<Map<String, Object>> list = doc.read(\"$.items\", new TypeRef<List<Map<String, Object>>>() {});","handlingStrategy":"type-guard","validationCode":"// compile-time: declare the anonymous subclass with an explicit type argument\nTypeRef<List<Map<String, Object>>> ref = new TypeRef<List<Map<String, Object>>>() {};","typeGuard":"static <T> TypeRef<T> typedRef(TypeRef<T> ref) { return Objects.requireNonNull(ref); } // always instantiate as new TypeRef<Concrete>() {}","tryCatchPattern":"try {\n    return doc.read(path, typeRef);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"No type info in TypeRef\")) {\n        throw new IllegalStateException(\"Pass new TypeRef<ConcreteType>() {} with a type argument\", e);\n    }\n    throw e;\n}","preventionTips":["Never instantiate raw TypeRef; always supply the generic argument.","Prefer read(path, Class) for simple types.","Add a unit test reading through each TypeRef used in production code."],"tags":["jsonpath","generics","typeref","reflection"],"backgroundTag":"invalid-constructor-argument","analyzedSha":"62a4c9f0f65ba3f625aa0867d64c528ba72d09ec","analyzedAt":"2026-09-11T11:36:00.448Z","contentChangedAt":"2026-09-11T11:36:00.448Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}