{"record":{"id":"7a686bb919f747d0","repo":"FasterXML/jackson-databind","slug":"annotationintrospector-returned-class-expec","errorCode":null,"errorMessage":"AnnotationIntrospector returned `Class<{}>`; expected `Class<Converter>`","messagePattern":"AnnotationIntrospector returned `Class<(.+?)>`; expected `Class<Converter>`","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"src/main/java/tools/jackson/databind/cfg/MapperConfigBase.java","lineNumber":748,"sourceCode":"            Object converterDef)\n    {\n        if (converterDef == null) {\n            return null;\n        }\n        if (converterDef instanceof Converter<?,?>) {\n            return (Converter<Object,Object>) converterDef;\n        }\n        if (!(converterDef instanceof Class)) {\n            throw new IllegalStateException(\"`AnnotationIntrospector` returned `Converter` definition of type \"\n                    +ClassUtil.classNameOf(converterDef)+\"; expected type `Converter` or `Class<Converter>` instead\");\n        }\n        Class<?> converterClass = (Class<?>)converterDef;\n        // there are some known \"no class\" markers to consider too:\n        if (converterClass == Converter.None.class || ClassUtil.isBogusClass(converterClass)) {\n            return null;\n        }\n        if (!Converter.class.isAssignableFrom(converterClass)) {\n            throw new IllegalStateException(\"AnnotationIntrospector returned `Class<\"\n                    +ClassUtil.classNameOf(converterClass)+\"`>; expected `Class<Converter>`\");\n        }\n        HandlerInstantiator hi = getHandlerInstantiator();\n        Converter<?,?> conv = (hi == null) ? null : hi.converterInstance(this, annotated, converterClass);\n        if (conv == null) {\n            conv = (Converter<?,?>) ClassUtil.createInstance(converterClass,\n                    canOverrideAccessModifiers());\n        }\n        return (Converter<Object,Object>) conv;\n    }\n}\n","sourceCodeStart":730,"sourceCodeEnd":760,"githubUrl":"https://github.com/FasterXML/jackson-databind/blob/a50c7d2a1d57234ac4adf70dbd88ac90db6436e4/src/main/java/tools/jackson/databind/cfg/MapperConfigBase.java#L730-L760","documentation":"Thrown by MapperConfigBase._createConverter when the introspector returns a Class for a converter, but that Class does not implement Converter. Jackson can only instantiate converter classes that satisfy the Converter interface, so any other class is rejected.","triggerScenarios":"An introspector (or @JsonDeserialize(converter=...) / @JsonSerialize(converter=...)) returns a Class that is not assignable to Converter<?,?> — e.g. a Function, a Supplier, a builder, or an unrelated bean.","commonSituations":"Pointing the converter annotation at the wrong class (a builder, a formatter, a DTO); a refactor that renamed or moved the converter without updating the annotation; confusing a Converter with a ValueSerializer/ValueDeserializer.","solutions":["Make the referenced class implement Converter<?,?> (override convert, getInputType, getOutputType).","If you intended a different conversion mechanism, use a custom ValueDeserializer/ValueSerializer instead of a Converter.","Verify the class referenced in @JsonSerialize(converter=...) / @JsonDeserialize(converter=...) actually implements Converter."],"exampleFix":"// before\n@JsonDeserialize(converter = StringReverser.class) // does NOT implement Converter\nclass StringReverser { String apply(String s){ return new StringBuilder(s).reverse().toString(); } }\n// after\nclass StringReverser implements Converter<String,String> {\n    public String convert(String s){ return new StringBuilder(s).reverse().toString(); }\n    public JavaType getInputType(TypeFactory f){ return f.constructType(String.class); }\n    public JavaType getOutputType(TypeFactory f){ return f.constructType(String.class); }\n}","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"static boolean isConverterClass(Class<?> c) {\n    return c != null && Converter.class.isAssignableFrom(c);\n}","tryCatchPattern":null,"preventionTips":["Verify the class referenced by converter annotations implements Converter<?,?> before wiring.","Keep converters in a dedicated package to avoid pointing annotations at look-alike classes.","Distinguish Converter from ValueSerializer/ValueDeserializer when annotating."],"tags":["annotation-introspector","converter","type-mismatch"],"analyzedSha":"a50c7d2a1d57234ac4adf70dbd88ac90db6436e4","analyzedAt":"2026-08-06T20:31:51.404Z","schemaVersion":2},"datasetVersion":"2026-08-07T02:17:10.218Z"}