{"record":{"id":"610f77d9f2b43c86","repo":"FasterXML/jackson-databind","slug":"cannot-construct-enummap-generic-key-type-not-a","errorCode":null,"errorMessage":"Cannot construct EnumMap; generic (key) type not available","messagePattern":"Cannot construct EnumMap; generic \\(key\\) type not available","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/main/java/tools/jackson/databind/deser/BasicDeserializerFactory.java","lineNumber":925,"sourceCode":"            Class<?> mapClass = type.getRawClass();\n            // [databind#1853]: Map `Map<ENUM,x>` to `EnumMap<ENUM,x>`\n            if ((mapClass == Map.class) && keyType.isEnumType()) {\n                mapClass = EnumMap.class;\n                type = (MapType) config.getTypeFactory().constructSpecializedType(type, mapClass);\n//                type = (MapType) config.getTypeFactory().constructMapType(mapClass, keyType, contentType);\n            }\n            if (EnumMap.class.isAssignableFrom(mapClass)) {\n                ValueInstantiator inst;\n\n                // 06-Mar-2017, tatu: Should only need to check ValueInstantiator for\n                //    custom sub-classes, see [databind#1544]\n                if (mapClass == EnumMap.class) {\n                    inst = null;\n                } else {\n                    inst = findValueInstantiator(ctxt, beanDescRef);\n                }\n                if (!keyType.isEnumImplType()) {\n                    throw new IllegalArgumentException(\"Cannot construct EnumMap; generic (key) type not available\");\n                }\n                deser = new EnumMapDeserializer(type, inst, null,\n                        contentDeser, contentTypeDeser, null);\n            }\n\n            // Otherwise, generic handler works ok.\n\n            /* But there is one more twist: if we are being asked to instantiate\n             * an interface or abstract Map, we need to either find something\n             * that implements the thing, or give up.\n             *\n             * Note that we do NOT try to guess based on secondary interfaces\n             * here; that would probably not work correctly since casts would\n             * fail later on (as the primary type is not the interface we'd\n             * be implementing)\n             */\n            if (deser == null) {\n                if (type.isInterface() || type.isAbstract()) {","sourceCodeStart":907,"sourceCodeEnd":943,"githubUrl":"https://github.com/FasterXML/jackson-databind/blob/a50c7d2a1d57234ac4adf70dbd88ac90db6436e4/src/main/java/tools/jackson/databind/deser/BasicDeserializerFactory.java#L907-L943","documentation":"Thrown when constructing a deserializer for an EnumMap whose key type cannot be resolved to a concrete enum. Because of generic erasure, Jackson needs the key's enum class at build time; if only a raw EnumMap or a non-enum key is visible, it cannot wire the EnumMapDeserializer.","triggerScenarios":"Deserializing into a raw EnumMap (no type parameters), EnumMap<?, ?>, or a type where the key generic argument was erased or unavailable (raw field, Object-typed reference, or a TypeReference that doesn't carry the enum).","commonSituations":"Raw-typed fields/variables; reflective code that loses generics; JSON deserialized to Object then converted; interface return types that drop the enum parameter; legacy pre-generic APIs.","solutions":["Declare the target with concrete generics: EnumMap<MyEnum, ValueType>.","Use a TypeReference<EnumMap<MyEnum, ValueType>>(){} at read boundaries to preserve generic info.","Avoid raw EnumMap; if unavoidable, deserialize into a concrete Map<MyEnum, ValueType> first, then copy into an EnumMap.","Ensure the field/method signature carries the enum key type through the entire call chain."],"exampleFix":"// before\nObject result = mapper.readValue(json, EnumMap.class); // raw -> throws\n// after\nEnumMap<MyEnum, String> result = mapper.readValue(json,\n        new TypeReference<EnumMap<MyEnum, String>>(){});","handlingStrategy":"validation","validationCode":"JavaType t = mapper.getTypeFactory()\n    .constructType(new TypeReference<EnumMap<MyEnum, X>>(){});\nif (!t.getKeyType().isEnumType() || !t.getKeyType().isEnumImplType()) {\n    throw new IllegalStateException(\"EnumMap key type is not a concrete enum: \" + t.getKeyType());\n}\nmapper.readValue(json, t);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never deserialize into raw EnumMap; always carry the enum key generic via TypeReference.","Preserve generic info through the entire call chain (field/method signatures).","Unit-test deserialization of generic map types with representative payloads."],"tags":["enummap","generics","type-erasure","deserialization"],"analyzedSha":"a50c7d2a1d57234ac4adf70dbd88ac90db6436e4","analyzedAt":"2026-08-06T20:31:51.404Z","schemaVersion":2},"datasetVersion":"2026-08-07T02:17:10.218Z"}