{"record":{"id":"7465f716b2620776","repo":"FasterXML/jackson-databind","slug":"annotationintrospector-returned-class-expected-7465f7","errorCode":null,"errorMessage":"AnnotationIntrospector returned Class {}; expected Class<ValueInstantiator>","messagePattern":"AnnotationIntrospector returned Class (.+?); expected Class<ValueInstantiator>","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"src/main/java/tools/jackson/databind/deser/BasicDeserializerFactory.java","lineNumber":294,"sourceCode":"            return null;\n        }\n\n        ValueInstantiator inst;\n\n        if (instDef instanceof ValueInstantiator valueInstantiator) {\n            return valueInstantiator;\n        }\n        if (!(instDef instanceof Class)) {\n            throw new IllegalStateException(\"AnnotationIntrospector returned key deserializer definition of type \"\n                    +instDef.getClass().getName()\n                    +\"; expected type KeyDeserializer or Class<KeyDeserializer> instead\");\n        }\n        Class<?> instClass = (Class<?>)instDef;\n        if (ClassUtil.isBogusClass(instClass)) {\n            return null;\n        }\n        if (!ValueInstantiator.class.isAssignableFrom(instClass)) {\n            throw new IllegalStateException(\"AnnotationIntrospector returned Class \"+instClass.getName()\n                    +\"; expected Class<ValueInstantiator>\");\n        }\n        HandlerInstantiator hi = config.getHandlerInstantiator();\n        if (hi != null) {\n            inst = hi.valueInstantiatorInstance(config, annotated, instClass);\n            if (inst != null) {\n                return inst;\n            }\n        }\n        return (ValueInstantiator) ClassUtil.createInstance(instClass,\n                config.canOverrideAccessModifiers());\n    }\n\n    /*\n    /**********************************************************************\n    /* Creator introspection: new (2.18) helper methods\n    /**********************************************************************\n     */","sourceCodeStart":276,"sourceCodeEnd":312,"githubUrl":"https://github.com/FasterXML/jackson-databind/blob/87876ca5c0569b4933aec2d30d6225e4b9ba3a43/src/main/java/tools/jackson/databind/deser/BasicDeserializerFactory.java#L276-L312","documentation":"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.","triggerScenarios":"Annotating a type with @JsonValueInstantiator(Class) where Class does not extend ValueInstantiator, or a custom introspector returning such a class.","commonSituations":"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.","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."],"exampleFix":"// before\n@JsonValueInstantiator(MyFactory.class)\npublic class MyFactory { public static Value create(){...} }\n\n// after\n@JsonValueInstantiator(MyValueInstantiator.class)\npublic class MyValueInstantiator extends ValueInstantiator {\n    @Override public Value createUsingDefault(DeserializationContext ctxt){...}\n    // ... other required overrides\n}","handlingStrategy":"type-guard","validationCode":"Class<?> cls = (Class<?>) introspector.findValueInstantiator(annotated);\nif (cls != null && !ValueInstantiator.class.isAssignableFrom(cls)) {\n    throw new IllegalStateException(cls + \" is not a ValueInstantiator\");\n}","typeGuard":"boolean isInstantiatorClass(Class<?> c) {\n    return c != null && ValueInstantiator.class.isAssignableFrom(c);\n}","tryCatchPattern":null,"preventionTips":["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."],"tags":["jackson","introspector","value-instantiator","annotation","config"],"backgroundTag":null,"analyzedSha":"87876ca5c0569b4933aec2d30d6225e4b9ba3a43","analyzedAt":"2026-08-11T12:55:24.033Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}