{"record":{"id":"fcc3d396662be17e","repo":"apache/dubbo","slug":"name-filed-should-be-string","errorCode":null,"errorMessage":"`name` filed should be string!","messagePattern":"`name` filed should be string!","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"dubbo-common/src/main/java/org/apache/dubbo/common/utils/PojoUtils.java","lineNumber":472,"sourceCode":"        if (pojo instanceof Map<?, ?> && type != null) {\n            Object className = ((Map<Object, Object>) pojo).get(\"class\");\n            if (className instanceof String) {\n                if (!CLASS_NOT_FOUND_CACHE.containsKey(className)) {\n                    try {\n                        type = DefaultSerializeClassChecker.getInstance()\n                                .loadClass(ClassUtils.getClassLoader(), (String) className);\n                    } catch (ClassNotFoundException e) {\n                        CLASS_NOT_FOUND_CACHE.put((String) className, NOT_FOUND_VALUE);\n                    }\n                }\n            }\n\n            // special logic for enum\n            if (type.isEnum()) {\n                Object name = ((Map<Object, Object>) pojo).get(\"name\");\n                if (name != null) {\n                    if (!(name instanceof String)) {\n                        throw new IllegalArgumentException(\"`name` filed should be string!\");\n                    } else {\n                        return Enum.valueOf((Class<Enum>) type, (String) name);\n                    }\n                }\n            }\n            Map<Object, Object> map;\n            // when return type is not the subclass of return type from the signature and not an interface\n            if (!type.isInterface() && !type.isAssignableFrom(pojo.getClass())) {\n                try {\n                    map = (Map<Object, Object>) type.getDeclaredConstructor().newInstance();\n                    Map<Object, Object> mapPojo = (Map<Object, Object>) pojo;\n                    map.putAll(mapPojo);\n                    if (GENERIC_WITH_CLZ) {\n                        map.remove(\"class\");\n                    }\n                } catch (Exception e) {\n                    // ignore error\n                    map = (Map<Object, Object>) pojo;","sourceCodeStart":454,"sourceCodeEnd":490,"githubUrl":"https://github.com/apache/dubbo/blob/3a3043227f5571d25eb2889de5bca22f2914843b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/PojoUtils.java#L454-L490","documentation":"When PojoUtils.realize encounters a Map representing an enum type, it extracts the 'name' key to reconstruct the enum constant via Enum.valueOf. If the value associated with 'name' is non-null but not a String (e.g. an Integer or another Map), Enum.valueOf cannot be called and an IllegalArgumentException is thrown.","triggerScenarios":"Calling PojoUtils.realize on a Map that targets an enum class, where the 'name' entry is a non-String type. This happens during generic RPC deserialization when the wire format (e.g. a custom JSON parser or a non-Java client) sends the enum name as a numeric ordinal or a structured object instead of a plain string.","commonSituations":"A non-Java consumer (Python, Go, Node.js) calling a Dubbo service via generic invocation that sends an enum as {\"name\": 1} (ordinal) instead of {\"name\": \"ACTIVE\"}. Also a misconfigured serializer or a manual Map construction where the 'name' key was set to the wrong type.","solutions":["Ensure the generic representation of an enum always uses a String value for the 'name' key matching an actual enum constant name.","If the source sends ordinals, convert them to the enum constant name before passing to realize.","On the consumer side, verify the serialization framework encodes enums as their name string, not ordinal.","For custom Map construction, explicitly cast: map.put(\"name\", enumValue.name())."],"exampleFix":"// before\nMap<String, Object> map = new HashMap<>();\nmap.put(\"name\", 1); // ordinal — throws\nMyEnum result = (MyEnum) PojoUtils.realize(map, MyEnum.class);\n// after\nmap.put(\"name\", MyEnum.ACTIVE.name()); // String constant name","handlingStrategy":"validation","validationCode":"// Validate enum 'name' field is a String before calling realize\nif (type.isEnum() && pojo instanceof Map) {\n    Object nameVal = ((Map<?, ?>) pojo).get(\"name\");\n    if (nameVal != null && !(nameVal instanceof String)) {\n        throw new IllegalArgumentException(\n            \"Enum 'name' must be String, got \" + nameVal.getClass());\n    }\n}\nPojoUtils.realize(pojo, type);","typeGuard":"// Type guard for enum map representations\nstatic boolean isValidEnumMap(Object pojo, Class<?> type) {\n    if (!type.isEnum() || !(pojo instanceof Map)) return true;\n    Object name = ((Map<?, ?>) pojo).get(\"name\");\n    return name == null || name instanceof String;\n}","tryCatchPattern":null,"preventionTips":["When constructing generic Maps for enums, always use enumConstant.name() as the 'name' value.","For non-Java consumers, document that enum fields must be sent as their String name, not ordinal.","Validate incoming Maps from non-Java clients before passing to realize."],"tags":["pojo","enum","deserialization","type-mismatch"],"backgroundTag":null,"analyzedSha":"3a3043227f5571d25eb2889de5bca22f2914843b","analyzedAt":"2026-08-14T00:43:19.853Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}