{"record":{"id":"81ef59316e836f9f","repo":"spring-projects/spring-ai","slug":"failed-to-convert-json-schema-to-openapi-format","errorCode":null,"errorMessage":"Failed to convert JSON Schema to OpenAPI format: ","messagePattern":"Failed to convert JSON Schema to OpenAPI format: ","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"models/spring-ai-google-genai/src/main/java/org/springframework/ai/google/genai/schema/JsonSchemaConverter.java","lineNumber":81,"sourceCode":"\t */\n\tpublic static ObjectNode convertToOpenApiSchema(ObjectNode jsonSchemaNode) {\n\t\tAssert.notNull(jsonSchemaNode, \"JSON Schema node must not be null\");\n\t\tAssert.isTrue(!jsonSchemaNode.has(\"$defs\"), \"Google's Structured Output schema doesn't support $defs property\");\n\n\t\ttry {\n\t\t\t// Convert to OpenAPI schema using our custom conversion logic\n\t\t\tObjectNode openApiSchema = convertSchema(jsonSchemaNode,\n\t\t\t\t\tJacksonUtils.getDefaultJsonMapper().getNodeFactory());\n\n\t\t\t// Add OpenAPI-specific metadata\n\t\t\tif (!openApiSchema.has(\"openapi\")) {\n\t\t\t\topenApiSchema.put(\"openapi\", \"3.0.0\");\n\t\t\t}\n\n\t\t\treturn openApiSchema;\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tthrow new IllegalStateException(\"Failed to convert JSON Schema to OpenAPI format: \" + e.getMessage(), e);\n\t\t}\n\t}\n\n\t/**\n\t * Copies common properties from source to target node.\n\t * @param source The source ObjectNode containing JSON Schema properties\n\t * @param target The target ObjectNode to copy properties to\n\t */\n\tprivate static void copyCommonProperties(ObjectNode source, ObjectNode target) {\n\t\tAssert.notNull(source, \"Source node must not be null\");\n\t\tAssert.notNull(target, \"Target node must not be null\");\n\t\tString[] commonProperties = {\n\t\t\t\t// Core schema properties\n\t\t\t\t\"format\", \"description\", \"default\", \"maximum\", \"minimum\", \"maxLength\", \"minLength\", \"pattern\", \"enum\",\n\t\t\t\t\"multipleOf\", \"uniqueItems\",\n\t\t\t\t// OpenAPI specific properties\n\t\t\t\t\"example\", \"deprecated\", \"readOnly\", \"writeOnly\", \"discriminator\", \"xml\", \"externalDocs\" };\n","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/models/spring-ai-google-genai/src/main/java/org/springframework/ai/google/genai/schema/JsonSchemaConverter.java#L63-L99","documentation":"JsonSchemaConverter.convertToOpenApiSchema(node, schemaType) rethrows any exception during the JSON Schema -> OpenAPI transformation as an IllegalStateException. The library throws this when the input ObjectNode has a shape the converter cannot transform (unexpected nodes, malformed nesting) or any internal error occurs.","triggerScenarios":"Passing an ObjectNode that is not a valid JSON Schema object (missing 'type'/'properties', null root, arrays where objects expected) so property-copy/transformation code throws.","commonSituations":"Programmatically built schema nodes missing required fields, schemas combining JSON Schema draft features unsupported by OpenAPI 3.0, or passing a non-object node (e.g., readTree returned an array).","solutions":["Validate the input node is a valid JSON Schema object before converting","Remove unsupported JSON Schema keywords (e.g., $ref/$schema) not handled by the converter","Inspect the chained cause message for the specific node that failed","Ensure readTree produced an ObjectNode, not an array/scalar"],"exampleFix":"// before\nObjectNode openApi = JsonSchemaConverter.convertToOpenApiSchema(node, \"OPENAPI\");\n// after\nif (!node.isObject() || !node.has(\"type\")) {\n    throw new IllegalArgumentException(\"input is not a JSON Schema object\");\n}\nObjectNode openApi = JsonSchemaConverter.convertToOpenApiSchema(node, \"OPENAPI\");","handlingStrategy":"validation","validationCode":"if (node == null || !node.isObject() || !node.has(\"type\")) {\n    throw new IllegalArgumentException(\"not a JSON Schema object node\");\n}","typeGuard":"boolean isJsonSchemaObject(com.fasterxml.jackson.databind.JsonNode n) {\n    return n != null && n.isObject() && n.hasNonNull(\"type\") && !n.has(\"$ref\");\n}","tryCatchPattern":"try {\n    ObjectNode openApi = JsonSchemaConverter.convertToOpenApiSchema(node, \"OPENAPI\");\n} catch (IllegalStateException e) {\n    logger.error(\"schema conversion failed: {}\", e.getCause() != null ? e.getCause().getMessage() : e.getMessage());\n    throw e;\n}","preventionTips":["Validate inputs are ObjectNode with 'type' set","Remove JSON Schema keywords unsupported by OpenAPI 3.0","Unit-test conversion of all schemas your app ships","Check the chained cause to locate the offending node"],"tags":["json-schema","openapi","conversion","schema"],"backgroundTag":"schema-validation-failed","analyzedSha":"98a7beda4f29d80a71c5837eb4053b03a93a46f7","analyzedAt":"2026-09-11T14:15:49.441Z","contentChangedAt":"2026-09-11T14:15:49.441Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}