json-path/JsonPath · error · IllegalArgumentException

No type info in TypeRef

Error message

No type info in TypeRef

What it means

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.

Solutions

  1. Always subclass with an explicit type argument: new TypeRef<List<String>>() {}.
  2. If the target type is a simple class, pass the Class directly (read(path, Class)) instead of TypeRef.
  3. Add a compile-time check or unit test exercising the TypeRef read so raw usage fails fast in review.

Example fix

// before
List<Map<String, Object>> list = doc.read("$.items", new TypeRef() {});
// after
List<Map<String, Object>> list = doc.read("$.items", new TypeRef<List<Map<String, Object>>>() {});
Defensive patterns

Strategy: type-guard

Validate before calling

// compile-time: declare the anonymous subclass with an explicit type argument
TypeRef<List<Map<String, Object>>> ref = new TypeRef<List<Map<String, Object>>>() {};

Type guard

static <T> TypeRef<T> typedRef(TypeRef<T> ref) { return Objects.requireNonNull(ref); } // always instantiate as new TypeRef<Concrete>() {}

Try / catch

try {
    return doc.read(path, typeRef);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("No type info in TypeRef")) {
        throw new IllegalStateException("Pass new TypeRef<ConcreteType>() {} with a type argument", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: 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>>>(){}.

Common situations: 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.

Related errors


AI-assisted analysis of json-path/JsonPath@62a4c9f0f6 (2026-09-11). Data as JSON: /api/errors/e6776e3a3f0c672d. Report an issue: GitHub.

Appendix: source

Thrown at json-path/src/main/java/com/jayway/jsonpath/TypeRef.java:37


/**
 * Used to specify generic type information in {@link com.jayway.jsonpath.ReadContext}
 *
 * <code>
 *       TypeRef ref = new TypeRef<List<Integer>>() { };
 * </code>
 *
 * @param <T>
 */
public abstract class TypeRef<T> implements Comparable<TypeRef<T>> {
    protected final Type type;
    
    protected TypeRef()
    {
        Type superClass = getClass().getGenericSuperclass();
        if (superClass instanceof Class<?>) {
            throw new IllegalArgumentException("No type info in TypeRef");
        }
        type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
    }

    public Type getType() { return type; }
    
    /**
     * The only reason we define this method (and require implementation
     * of <code>Comparable</code>) is to prevent constructing a
     * reference without type information.
     */
    @Override
    public int compareTo(TypeRef<T> o) {
        return 0;
    }
}

View on GitHub (pinned to 62a4c9f0f6)