{"record":{"id":"2be63545036faeca","repo":"apache/dubbo","slug":"value-s-for-idx-d-in-s-is-not-string","errorCode":null,"errorMessage":"value '%s' for idx %d in '%s' is not string","messagePattern":"value '(.+?)' for idx (.+?) in '(.+?)' is not string","errorType":"exception","errorClass":"ClassCastException","httpStatus":null,"severity":"error","filePath":"dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/AbstractJsonUtilImpl.java","lineNumber":246,"sourceCode":"            if (!(rawList.get(i) instanceof Map)) {\n                throw new ClassCastException(\n                        String.format(\"value %s for idx %d in %s is not object\", rawList.get(i), i, rawList));\n            }\n        }\n        return (List<Map<String, ?>>) rawList;\n    }\n\n    /**\n     * Casts a list of unchecked JSON values to a list of String. If the given list\n     * contains a value that is not a String, throws an exception.\n     */\n    @SuppressWarnings(\"unchecked\")\n    @Override\n    public List<String> checkStringList(List<?> rawList) {\n        assert rawList != null;\n        for (int i = 0; i < rawList.size(); i++) {\n            if (!(rawList.get(i) instanceof String)) {\n                throw new ClassCastException(\n                        String.format(\"value '%s' for idx %d in '%s' is not string\", rawList.get(i), i, rawList));\n            }\n        }\n        return (List<String>) rawList;\n    }\n}\n","sourceCodeStart":228,"sourceCodeEnd":253,"githubUrl":"https://github.com/apache/dubbo/blob/3a3043227f5571d25eb2889de5bca22f2914843b/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/AbstractJsonUtilImpl.java#L228-L253","documentation":"Thrown by AbstractJsonUtilImpl.checkStringList(List) when iterating rawList and an element is not a String. The method casts an unchecked List<?> into List<String>, validating each entry; the first non-String entry aborts with a ClassCastException naming the value, its index, and the whole list. getListOfStrings delegates to getList then checkStringList, so the same exception surfaces through that path.","triggerScenarios":"jsonUtil.checkStringList(rawList) (or getListOfStrings(obj,key)) where rawList contains at least one element that is not a String — e.g. [1, 2, 3], [{\"a\":1}], [true]. A list of pure strings passes.","commonSituations":"A JSON array of numbers/booleans where an array of strings was expected; a backend that emits numeric IDs as JSON numbers instead of strings; mixed-type arrays from a lenient producer; an enum/code list returned as numbers; a payload version change.","solutions":["Normalize each entry with String.valueOf before validation, or filter to String entries: raw.stream().filter(String.class::isInstance).map(String.class::cast).collect(toList()).","If the schema requires all-string entries, fix the upstream producer to emit strings.","Use getList (untyped) if heterogeneous entries are valid, then coerce per element.","Catch ClassCastException and report the offending index for triage."],"exampleFix":"// before\nList<String> tags = jsonUtil.checkStringList(raw); // contains Integer 7\n// after - coerce all entries to String\nList<String> tags = raw.stream()\n    .map(java.util.Objects::toString)\n    .collect(java.util.stream.Collectors.toList());","handlingStrategy":"type-guard","validationCode":"List<?> raw = ...;\nfor (Object e : raw) {\n    if (!(e instanceof String)) {\n        raw = raw.stream().map(java.util.Objects::toString).collect(java.util.stream.Collectors.toList());\n        break;\n    }\n}\nreturn jsonUtil.checkStringList(raw);","typeGuard":"private static boolean allStrings(List<?> rawList) {\n    for (Object e : rawList) if (!(e instanceof String)) return false;\n    return true;\n}","tryCatchPattern":"try {\n    return jsonUtil.checkStringList(rawList);\n} catch (ClassCastException e) {\n    // message names the offending index; coerce all entries to String\n    return rawList.stream()\n        .map(java.util.Objects::toString)\n        .collect(java.util.stream.Collectors.toList());\n}","preventionTips":["Coerce list entries with String.valueOf/Objects::toString before validation when non-strings are possible.","Validate array element types against the schema at trust boundaries.","Use getList (untyped) with per-element handling if mixed types are legitimate."],"tags":["json","type-mismatch","classcast","list-validation","jsonutil","dubbo-common"],"backgroundTag":null,"analyzedSha":"3a3043227f5571d25eb2889de5bca22f2914843b","analyzedAt":"2026-08-14T00:43:19.853Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}