FasterXML/jackson-databind · error · IllegalStateException

AnnotationIntrospector returned Class

Error message

AnnotationIntrospector returned Class {}; expected Class<ValueInstantiator>

What it means

Thrown by BasicDeserializerFactory._valueInstantiatorInstance when an AnnotationIntrospector returned a Class that is not assignable to ValueInstantiator. The @JsonValueInstantiator annotation (or introspector equivalent) must reference a ValueInstantiator subclass; any other class is rejected at instantiation time.

Solutions

  1. Make the referenced class extend ValueInstantiator and implement the required methods (getDefaultCreatorArguments, createUsingDefault, etc.).
  2. Point @JsonValueInstantiator at the correct ValueInstantiator subclass.
  3. If you only need a factory/builder pattern, use @JsonCreator / builder support instead of @JsonValueInstantiator.

Example fix

// before
@JsonValueInstantiator(MyFactory.class)
public class MyFactory { public static Value create(){...} }

// after
@JsonValueInstantiator(MyValueInstantiator.class)
public class MyValueInstantiator extends ValueInstantiator {
    @Override public Value createUsingDefault(DeserializationContext ctxt){...}
    // ... other required overrides
}
Defensive patterns

Strategy: type-guard

Validate before calling

Class<?> cls = (Class<?>) introspector.findValueInstantiator(annotated);
if (cls != null && !ValueInstantiator.class.isAssignableFrom(cls)) {
    throw new IllegalStateException(cls + " is not a ValueInstantiator");
}

Type guard

boolean isInstantiatorClass(Class<?> c) {
    return c != null && ValueInstantiator.class.isAssignableFrom(c);
}

Prevention

When it happens

Trigger: Annotating a type with @JsonValueInstantiator(Class) where Class does not extend ValueInstantiator, or a custom introspector returning such a class.

Common situations: Pointing @JsonValueInstantiator at a plain factory/builder class that is not a ValueInstantiator; refactoring a class so it no longer extends ValueInstantiator while keeping the annotation; wrong class literal referenced.

Related errors


AI-assisted analysis of FasterXML/jackson-databind@87876ca5c0 (2026-08-11). Data as JSON: /api/errors/7465f716b2620776. Report an issue: GitHub.

Appendix: source

Thrown at src/main/java/tools/jackson/databind/deser/BasicDeserializerFactory.java:294

            return null;
        }

        ValueInstantiator inst;

        if (instDef instanceof ValueInstantiator valueInstantiator) {
            return valueInstantiator;
        }
        if (!(instDef instanceof Class)) {
            throw new IllegalStateException("AnnotationIntrospector returned key deserializer definition of type "
                    +instDef.getClass().getName()
                    +"; expected type KeyDeserializer or Class<KeyDeserializer> instead");
        }
        Class<?> instClass = (Class<?>)instDef;
        if (ClassUtil.isBogusClass(instClass)) {
            return null;
        }
        if (!ValueInstantiator.class.isAssignableFrom(instClass)) {
            throw new IllegalStateException("AnnotationIntrospector returned Class "+instClass.getName()
                    +"; expected Class<ValueInstantiator>");
        }
        HandlerInstantiator hi = config.getHandlerInstantiator();
        if (hi != null) {
            inst = hi.valueInstantiatorInstance(config, annotated, instClass);
            if (inst != null) {
                return inst;
            }
        }
        return (ValueInstantiator) ClassUtil.createInstance(instClass,
                config.canOverrideAccessModifiers());
    }

    /*
    /**********************************************************************
    /* Creator introspection: new (2.18) helper methods
    /**********************************************************************
     */

View on GitHub (pinned to 87876ca5c0)