{"record":{"id":"6361569f3367db69","repo":"spring-projects/spring-ai","slug":"failed-to-parse-json-schema-636156","errorCode":null,"errorMessage":"Failed to parse JSON Schema","messagePattern":"Failed to parse JSON Schema","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"spring-ai-model/src/main/java/org/springframework/ai/tool/augment/ToolInputSchemaAugmenter.java","lineNumber":130,"sourceCode":"\t\t\t\t\tif (schemaObjectNode.has(\"required\")) {\n\t\t\t\t\t\trequiredArray = (ArrayNode) schemaObjectNode.get(\"required\");\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\trequiredArray = JacksonUtils.getDefaultJsonMapper().createArrayNode();\n\t\t\t\t\t\tschemaObjectNode.set(\"required\", requiredArray);\n\t\t\t\t\t}\n\t\t\t\t\trequiredArray.add(argument.name());\n\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn JacksonUtils.getDefaultJsonMapper()\n\t\t\t\t.writerWithDefaultPrettyPrinter()\n\t\t\t\t.writeValueAsString(schemaObjectNode);\n\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tthrow new RuntimeException(\"Failed to parse JSON Schema\", e);\n\t\t}\n\t}\n\n\t/**\n\t * Represents an extended argument type with additional metadata such as description\n\t * and required status.\n\t */\n\tpublic record AugmentedArgumentType(String name, Type type, String description, boolean required) {\n\t}\n\n}\n","sourceCodeStart":112,"sourceCodeEnd":142,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/spring-ai-model/src/main/java/org/springframework/ai/tool/augment/ToolInputSchemaAugmenter.java#L112-L142","documentation":"augmentToolInputSchema(String, ...) parses the tool's JSON Schema string into a Jackson ObjectNode, injects an augmented property, and serializes it back. Any exception during parse, mutation, or serialization is rethrown as a RuntimeException with this message. Note the message says 'parse' but the catch covers the whole method body, including serialization.","triggerScenarios":"Passing a malformed/non-JSON string as the tool input schema; passing empty or null schema text; a schema that cannot round-trip through the default Jackson mapper.","commonSituations":"Hand-written JSON Schema strings with trailing commas or comments; schemas obtained from another library's non-standard serialization; building schema strings by string concatenation instead of via Jackson.","solutions":["Validate the schema string parses as JSON (e.g. JacksonUtils.getDefaultJsonMapper().readTree(schema)) before augmenting.","Generate the base schema programmatically (e.g. from the tool's record via JsonSchemaGenerator) rather than hand-writing it.","Read the wrapped cause to identify whether the failure is in parsing or in writeValueAsString."],"exampleFix":"// before\nString augmented = ToolInputSchemaAugmenter.augmentToolInputSchema(\"{type: object}\", \"x\", String.class, \"d\", true); // invalid JSON\n// after\nString schema = \"\"\"{\"type\":\"object\",\"properties\":{}}\"\"\";\nString augmented = ToolInputSchemaAugmenter.augmentToolInputSchema(schema, \"x\", String.class, \"d\", true);","handlingStrategy":"validation","validationCode":"new com.fasterxml.jackson.databind.ObjectMapper().readTree(schemaString); // throws if the schema is not valid JSON","typeGuard":null,"tryCatchPattern":"try { augmented = ToolInputSchemaAugmenter.augmentToolInputSchema(schema, prop, type, desc, req); } catch (RuntimeException e) { throw new IllegalArgumentException(\"Tool input schema is not valid JSON: \" + e.getMessage(), e); }","preventionTips":["Generate JSON Schema programmatically instead of hand-writing strings.","Keep schema strings as text blocks or resources and validate them in tests."],"tags":["json","json-schema","parsing","spring-ai"],"backgroundTag":"json-parse-error","analyzedSha":"98a7beda4f29d80a71c5837eb4053b03a93a46f7","analyzedAt":"2026-09-11T14:15:49.441Z","contentChangedAt":"2026-09-11T14:15:49.441Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}