{"record":{"id":"15f567433578564e","repo":"alibaba/nacos","slug":"is-not-a-json-value","errorCode":null,"errorMessage":"{} is not a JSON value","messagePattern":"(.+?) is not a JSON value","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"ai/src/main/java/com/alibaba/nacos/ai/service/agent/metadata/AgentResourceExtSerializer.java","lineNumber":208,"sourceCode":"            return;\n        }\n        if (value instanceof List) {\n            for (Object item : (List<?>) value) {\n                validateJsonValue(item, fieldName);\n            }\n            return;\n        }\n        if (value instanceof Map) {\n            for (Map.Entry<?, ?> entry : ((Map<?, ?>) value).entrySet()) {\n                if (!(entry.getKey() instanceof String)) {\n                    throw new IllegalArgumentException(\n                        fieldName + \" contains a non-string JSON object key\");\n                }\n                validateJsonValue(entry.getValue(), fieldName);\n            }\n            return;\n        }\n        throw new IllegalArgumentException(fieldName + \" is not a JSON value\");\n    }\n    \n    private static void validateCatalog(AgentVersionCatalog catalog) {\n        AgentModelValidator.validateVersionCatalog(catalog);\n        List<AgentVersionCatalogEntry> versions = catalog.getOnlineVersions();\n        for (int i = 1; i < versions.size(); i++) {\n            String previous = versions.get(i - 1).getVersion();\n            String current = versions.get(i).getVersion();\n            if (AgentVersionComparator.compare(previous, current) <= 0) {\n                throw new IllegalArgumentException(\n                    \"Agent Version catalog must use descending Version order\");\n            }\n        }\n    }\n    \n    private static void validateOptionalAbsoluteUri(String value, String fieldName) {\n        if (value == null) {\n            return;","sourceCodeStart":190,"sourceCodeEnd":226,"githubUrl":"https://github.com/alibaba/nacos/blob/9b989acdf181d00898f2e8839257bb2b2a3cefe3/ai/src/main/java/com/alibaba/nacos/ai/service/agent/metadata/AgentResourceExtSerializer.java#L190-L226","documentation":"validateJsonValue() is the terminal fallback: any extension value that is not null, String, Boolean, a finite Number, List, or Map throws '<fieldName> is not a JSON value'. This rejects arbitrary Java objects that have no direct JSON representation (custom POJOs, dates, enums-as-objects, arrays of non-JSON types not wrapped in List).","triggerScenarios":"An extensions value is a Java object whose runtime type is none of the allowed categories — e.g. a UUID, an enum constant, a java.util.Date, a typed POJO, or a primitive array (int[]).","commonSituations":"Storing domain objects directly into extensions instead of converting to a JSON-compatible structure; using primitive arrays instead of List.","solutions":["Convert non-JSON values to a supported type first: UUID -> toString, Date/Instant -> ISO string, enum -> name(), int[] -> List<Integer>.","If you need a structured value, build a Map<String,Object> or List<Object>.","Add a pre-flight validator in tests that walks extensions and asserts each leaf is one of the allowed types."],"exampleFix":"// before\next.put(\"id\", java.util.UUID.randomUUID()); // not a JSON value\next.put(\"ports\", new int[]{8080, 8081}); // primitive array, not a List\n\n// after\next.put(\"id\", java.util.UUID.randomUUID().toString());\next.put(\"ports\", java.util.List.of(8080, 8081));","handlingStrategy":"type-guard","validationCode":"static boolean isJsonValue(Object v) {\n    if (v == null || v instanceof String || v instanceof Boolean || v instanceof Number\n            || v instanceof List || v instanceof Map) {\n        if (v instanceof Float) return Float.isFinite((Float) v);\n        if (v instanceof Double) return Double.isFinite((Double) v);\n        return true;\n    }\n    return false;\n}","typeGuard":"static boolean isJsonCompatible(Object v) {\n    if (v == null) return true;\n    if (v instanceof String || v instanceof Boolean) return true;\n    if (v instanceof Float) return Float.isFinite((Float) v);\n    if (v instanceof Double) return Double.isFinite((Double) v);\n    if (v instanceof Byte || v instanceof Short || v instanceof Integer || v instanceof Long) return true;\n    if (v instanceof List) return ((List<?>) v).stream().allMatch(AgentExtGuards::isJsonCompatible);\n    if (v instanceof Map) return ((Map<?,?>) v).keySet().stream().allMatch(k -> k instanceof String)\n            && ((Map<?,?>) v).values().stream().allMatch(AgentExtGuards::isJsonCompatible);\n    return false;\n}","tryCatchPattern":null,"preventionTips":["Convert UUID/Date/Instant/enum to String and primitive arrays to List before insertion.","Walk extensions once with isJsonCompatible before publishing.","Avoid putting domain POJOs into the free-form map."],"tags":["ai-registry","agent","extensions","type-violation"],"backgroundTag":null,"analyzedSha":"9b989acdf181d00898f2e8839257bb2b2a3cefe3","analyzedAt":"2026-08-14T07:17:31.569Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}