{"record":{"id":"71834f94d6b5e692","repo":"FasterXML/jackson-databind","slug":"unsuitable-method-decorated-with-jsoncreator","errorCode":null,"errorMessage":"Unsuitable method ({}) decorated with @JsonCreator (for Enum type {})","messagePattern":"Unsuitable method \\((.+?)\\) decorated with @JsonCreator \\(for Enum type (.+?)\\)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/main/java/tools/jackson/databind/deser/BasicDeserializerFactory.java","lineNumber":1283,"sourceCode":"                    Class<?> returnType = factory.getRawReturnType();\n                    // usually should be class, but may be just plain Enum<?> (for Enum.valueOf()?)\n                    if (returnType.isAssignableFrom(enumClass)) {\n                        // note: mostly copied from 'EnumDeserializer.deserializerForCreator(...)'\n                        if (factory.getRawParameterType(0) != String.class) {\n                            // [databind#2725]: Should not error out because (1) there may be good creator\n                            //   method and (2) this method may be valid for \"regular\" enum value deserialization\n                            // (leaving aside potential for multiple conflicting creators)\n//                            throw new IllegalArgumentException(\"Parameter #0 type for factory method (\"+factory+\") not suitable, must be java.lang.String\");\n                            continue;\n                        }\n                        if (config.canOverrideAccessModifiers()) {\n                            ClassUtil.checkAndFixAccess(factory.getMember(),\n                                    ctxt.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS));\n                        }\n                        return JDKKeyDeserializers.constructEnumKeyDeserializer(enumRes, factory, byEnumNamingResolver, byToStringResolver, byIndexResolver);\n                    }\n                }\n                throw new IllegalArgumentException(\"Unsuitable method (\"+factory+\") decorated with @JsonCreator (for Enum type \"\n                        +enumClass.getName()+\")\");\n            }\n        }\n        // Also, need to consider @JsonValue, if one found\n        return JDKKeyDeserializers.constructEnumKeyDeserializer(enumRes, byEnumNamingResolver, byToStringResolver, byIndexResolver);\n    }\n\n    /*\n    /**********************************************************************\n    /* DeserializerFactory impl: find explicitly supported types\n    /**********************************************************************\n     */\n\n    /**\n     * Method that can be used to check if databind module has deserializer\n     * for given (likely JDK) type: explicit meaning that it is not automatically\n     * generated for POJO.\n     *<p>","sourceCodeStart":1265,"sourceCodeEnd":1301,"githubUrl":"https://github.com/FasterXML/jackson-databind/blob/87876ca5c0569b4933aec2d30d6225e4b9ba3a43/src/main/java/tools/jackson/databind/deser/BasicDeserializerFactory.java#L1265-L1301","documentation":"Thrown by BasicDeserializerFactory when an enum type has a static factory method annotated @JsonCreator that Jackson wants to use for key (EnumMap/Enum key) deserialization, but the method signature is unsuitable. For the key-deserializer path, the factory must take exactly one parameter of type String and return a type assignable to the enum class; otherwise this error is raised.","triggerScenarios":"An enum declares @JsonCreator on a static method that has zero/multiple parameters, a non-String parameter, or a return type that is not compatible with the enum class, and Jackson attempts to build an enum key deserializer that would use it.","commonSituations":"Annotating a generic fromJson(Map)/fromJson(int) factory with @JsonCreator expecting it to be used for enum keys; sharing a creator between value and key deserialization where only a String-arg factory is valid; refactor that changed the parameter type.","solutions":["Ensure the @JsonCreator static factory used for enum key deserialization takes a single String argument and returns the enum type.","If the method is meant for value (not key) deserialization, move/annotate a separate String-arg factory, or remove @JsonCreator from the unsuitable method.","Use @JsonCreator(mode=Mode.DELEGATING) on a single-arg delegating constructor/factory with a String-compatible type."],"exampleFix":"// before: int parameter -> unsuitable for enum key deser\npublic enum Code {\n    @JsonCreator public static Code fromCode(int v){...}\n}\n\n// after: separate String-arg factory for key deser\npublic enum Code {\n    @JsonCreator public static Code fromKey(String name){...}\n}","handlingStrategy":"validation","validationCode":"// Validate the enum's @JsonCreator factory: single String param, return type assignable to enum.\nfor (Method m : enumClass.getMethods()) {\n    if (m.isAnnotationPresent(JsonCreator.class)\n        && Modifier.isStatic(m.getModifiers())\n        && (m.getParameterCount() != 1 || m.getParameterTypes()[0] != String.class\n            || !enumClass.isAssignableFrom(m.getReturnType()))) {\n        throw new IllegalStateException(\"Unsuitable enum creator: \" + m);\n    }\n}","typeGuard":"boolean isEnumKeyFactory(Method m, Class<? extends Enum> enumClass) {\n    return Modifier.isStatic(m.getModifiers())\n        && m.getParameterCount() == 1\n        && m.getParameterTypes()[0] == String.class\n        && enumClass.isAssignableFrom(m.getReturnType());\n}","tryCatchPattern":null,"preventionTips":["Keep enum @JsonCreator factories to a single String argument returning the enum.","Annotate value-deserialization creators separately from key-deserialization ones.","Test enum key deserialization (EnumMap/Map<Enum,?>) in unit tests."],"tags":["jackson","deserialization","enum","jsoncreator","annotation","factory-method"],"backgroundTag":null,"analyzedSha":"87876ca5c0569b4933aec2d30d6225e4b9ba3a43","analyzedAt":"2026-08-11T12:55:24.033Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}