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
- Make the referenced class extend ValueInstantiator and implement the required methods (getDefaultCreatorArguments, createUsingDefault, etc.).
- Point @JsonValueInstantiator at the correct ValueInstantiator subclass.
- 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
- Ensure @JsonValueInstantiator always points to a ValueInstantiator subclass.
- Prefer @JsonCreator for factory/builder patterns over @JsonValueInstantiator.
- Test mapper construction for every type using a custom instantiator.
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
- AnnotationIntrospector returned key deserializer definition…
- AnnotationIntrospector returned `Class<
- `AnnotationIntrospector` returned `Converter` definition of…
- AnnotationIntrospector returned deserializer definition of…
- Cannot pass null resolver
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)