{"record":{"id":"fcb9a043f46f0b90","repo":"alibaba/nacos","slug":"unknown-field","errorCode":null,"errorMessage":"Unknown {} field: {}","messagePattern":"Unknown (.+?) field: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"ai/src/main/java/com/alibaba/nacos/ai/service/agent/metadata/AgentResourceExtSerializer.java","lineNumber":397,"sourceCode":"    private static void validateOptionalJsonText(Map<?, ?> object, String field) {\n        if (object.containsKey(field) && !(object.get(field) instanceof String)) {\n            throw new IllegalArgumentException(field + \" must be a string\");\n        }\n    }\n    \n    private static void validateJsonInteger(Map<?, ?> object, String field) {\n        Object value = object.get(field);\n        if (!(value instanceof Byte || value instanceof Short || value instanceof Integer\n            || value instanceof Long)) {\n            throw new IllegalArgumentException(field + \" must be an integer\");\n        }\n    }\n    \n    private static void rejectUnknownFields(Map<?, ?> object, Set<String> allowedFields,\n        String objectName) {\n        for (Object field : object.keySet()) {\n            if (!allowedFields.contains(field)) {\n                throw new IllegalArgumentException(\n                    \"Unknown \" + objectName + \" field: \" + field);\n            }\n        }\n    }\n    \n    private static void validateSingleJsonValue(String json) {\n        try (JsonParser parser = STRICT_JSON_FACTORY.createParser(json)) {\n            if (parser.nextToken() == null) {\n                throw new IllegalArgumentException(\"AgentResourceExt JSON must not be empty\");\n            }\n            parser.skipChildren();\n            if (parser.nextToken() != null) {\n                throw new IllegalArgumentException(\n                    \"AgentResourceExt must contain one JSON value\");\n            }\n        } catch (IOException e) {\n            throw new IllegalArgumentException(\"Invalid AgentResourceExt\", e);\n        }","sourceCodeStart":379,"sourceCodeEnd":415,"githubUrl":"https://github.com/alibaba/nacos/blob/9b989acdf181d00898f2e8839257bb2b2a3cefe3/ai/src/main/java/com/alibaba/nacos/ai/service/agent/metadata/AgentResourceExtSerializer.java#L379-L415","documentation":"The ai_resource.ext JSON enforces a closed schema: only known fields are allowed at each nesting level. The rejectUnknownFields helper (line 396) throws this when any field is present that is not in the allowed set for that object. Allowed root fields: schemaVersion, displayName, iconUrl, provider, extensions, versionCatalog. Allowed provider fields: name, url. Allowed catalog fields: latestVersion, onlineVersions. Allowed catalog entry fields: version, labels, protocols.","triggerScenarios":"Deserializing ai_resource.ext JSON containing any unrecognized field at any level. For example, adding 'description' to the root, 'email' to provider, or 'releaseDate' to a catalog entry.","commonSituations":"Schema evolution where a new field was added without updating the serializer's allowed-field sets; importing agent metadata from a richer external schema; copy-paste from another resource type.","solutions":["Remove the unknown field identified in the error message from the JSON.","If the field is intentional, update the corresponding allowed-field Set in AgentResourceExtSerializer (ROOT_FIELDS, PROVIDER_FIELDS, CATALOG_FIELDS, or CATALOG_ENTRY_FIELDS) and add typed validation for it.","Discuss with maintainers before adding new fields, as per the spec-first coding guideline."],"exampleFix":"// before\n{\"schemaVersion\":1,\"description\":\"my agent\",\"versionCatalog\":{...}}\n// after\n{\"schemaVersion\":1,\"displayName\":\"my agent\",\"versionCatalog\":{...}}","handlingStrategy":"validation","validationCode":"Set<String> allowed = Set.of(\"schemaVersion\",\"displayName\",\"iconUrl\",\"provider\",\"extensions\",\"versionCatalog\");\nfor (Object key : root.keySet()) {\n    if (!allowed.contains(key)) {\n        throw new IllegalArgumentException(\"Unknown field: \" + key);\n    }\n}","typeGuard":"public static boolean hasOnlyKnownFields(Map<?,?> obj, Set<String> allowed) {\n    for (Object key : obj.keySet()) {\n        if (!allowed.contains(key)) return false;\n    }\n    return true;\n}","tryCatchPattern":"try {\n    AgentResourceExtSerializer.deserialize(json);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().startsWith(\"Unknown \")) {\n        // extract the field name and remove or rename it\n    }\n    throw e;\n}","preventionTips":["Familiarize yourself with the allowed field sets in AgentResourceExtSerializer before adding fields.","Use the typed AgentResourceExt DTO and its serialize() method so only known fields are emitted.","When evolving the schema, update both the allowed-field sets and the specs in the same change set."],"tags":["validation","ai-agent","json-schema","serialization","schema-evolution"],"backgroundTag":null,"analyzedSha":"9b989acdf181d00898f2e8839257bb2b2a3cefe3","analyzedAt":"2026-08-14T07:17:31.569Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}