{"record":{"id":"618ac72c7b7df85a","repo":"alibaba/nacos","slug":"agentresourceext-json-must-not-be-empty","errorCode":null,"errorMessage":"AgentResourceExt JSON must not be empty","messagePattern":"AgentResourceExt JSON must not be empty","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"ai/src/main/java/com/alibaba/nacos/ai/service/agent/metadata/AgentResourceExtSerializer.java","lineNumber":296,"sourceCode":"            Map<String, Object> version = new LinkedHashMap<String, Object>();\n            version.put(\"version\", entry.getVersion());\n            version.put(\"labels\", entry.getLabels());\n            version.put(\"protocols\", entry.getProtocols());\n            versions.add(version);\n        }\n        result.put(\"onlineVersions\", versions);\n        return result;\n    }\n    \n    private static void putIfPresent(Map<String, Object> target, String field, Object value) {\n        if (value != null) {\n            target.put(field, value);\n        }\n    }\n    \n    private static void validateJsonShape(String json) {\n        if (json == null || json.isEmpty()) {\n            throw new IllegalArgumentException(\"AgentResourceExt JSON must not be empty\");\n        }\n        validateSingleJsonValue(json);\n        final Map<?, ?> root;\n        try {\n            root = JacksonUtils.toObj(json, Map.class);\n        } catch (NacosDeserializationException e) {\n            throw new IllegalArgumentException(\"Invalid AgentResourceExt\", e);\n        }\n        if (root == null) {\n            throw new IllegalArgumentException(\"AgentResourceExt must be a JSON object\");\n        }\n        rejectUnknownFields(root, ROOT_FIELDS, \"AgentResourceExt\");\n        validateJsonInteger(root, \"schemaVersion\");\n        validateOptionalJsonText(root, \"displayName\");\n        validateOptionalJsonText(root, \"iconUrl\");\n        validateProviderShape(root);\n        validateExtensionsShape(root);\n        validateCatalogShape(root);","sourceCodeStart":278,"sourceCodeEnd":314,"githubUrl":"https://github.com/alibaba/nacos/blob/9b989acdf181d00898f2e8839257bb2b2a3cefe3/ai/src/main/java/com/alibaba/nacos/ai/service/agent/metadata/AgentResourceExtSerializer.java#L278-L314","documentation":"validateJsonShape(), the first step of deserialize(), rejects a null or empty input string before any JSON parsing. 'AgentResourceExt JSON must not be empty' means the caller passed null or \"\" as the ext JSON — there is nothing to parse. (The same message is also raised by validateSingleJsonValue if the JSON stream has no token.)","triggerScenarios":"deserialize() called with null/empty ai_resource.ext — e.g. reading an agent row whose ext column is empty/NULL, or an API handler deserializing a missing ext payload.","commonSituations":"An agent record persisted before the typed-ext feature existed (empty ext column), a DB migration that left ext empty, or a client omitting the ext field on a path that still requires it.","solutions":["If the ext column is legitimately empty, treat it as 'no extension' at the caller rather than calling deserialize(\"\").","For rows with empty ext, re-publish the agent with a well-formed ext payload to populate ai_resource.ext.","Guard the call site: only deserialize when the ext string is non-null and non-empty."],"exampleFix":"// before\nAgentResourceExt ext = AgentResourceExtSerializer.deserialize(row.getExt()); // row.getExt() is \"\"\n\n// after\nString raw = row.getExt();\nAgentResourceExt ext = (raw == null || raw.isEmpty()) ? null : AgentResourceExtSerializer.deserialize(raw);","handlingStrategy":"validation","validationCode":"static AgentResourceExt safeDeserialize(String raw) {\n    if (raw == null || raw.isEmpty()) return null; // treat as 'no extension'\n    return AgentResourceExtSerializer.deserialize(raw);\n}","typeGuard":"static boolean isNonEmptyJson(String raw) {\n    return raw != null && !raw.isEmpty() && !raw.trim().isEmpty();\n}","tryCatchPattern":"try {\n    AgentResourceExtSerializer.deserialize(rawJson);\n} catch (IllegalArgumentException e) {\n    if (\"AgentResourceExt JSON must not be empty\".equals(e.getMessage())) {\n        // ext column empty: re-publish or skip\n        return null;\n    }\n    throw e;\n}","preventionTips":["Guard deserialize callers to skip empty/null ext rather than parse.","Re-publish agents whose ext column is empty to populate it.","Never persist empty strings into ai_resource.ext."],"tags":["ai-registry","agent","deserialization","empty-input"],"backgroundTag":null,"analyzedSha":"9b989acdf181d00898f2e8839257bb2b2a3cefe3","analyzedAt":"2026-08-14T07:17:31.569Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}