{"record":{"id":"218f6db03e84fe27","repo":"alibaba/spring-ai-alibaba","slug":"schema-extensions-recursion-depth-limit-d-reache","errorCode":null,"errorMessage":"Schema extensions recursion depth limit(%d) reached.","messagePattern":"Schema extensions recursion depth limit\\((.+?)\\) reached\\.","errorType":"validation","errorClass":"YAMLException","httpStatus":null,"severity":"error","filePath":"spring-ai-alibaba-admin/spring-ai-alibaba-admin-server-core/src/main/java/com/alibaba/cloud/ai/studio/core/utils/api/OpenApiUtils.java","lineNumber":594,"sourceCode":"\t\t\t\t\t\t\t\tresult, 0));\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\treturn result;\n\t}\n\n\t/**\n\t * Checks schema extensions\n\t * @param schemaField Schema field name\n\t * @param schema Schema object\n\t * @param resultList List to store results\n\t * @param currentDepth Current recursion depth\n\t * @throws YAMLException If recursion depth limit is reached\n\t */\n\tprivate static void checkSchemaExtension(String schemaField, Schema<?> schema, List<ApiParameter> resultList,\n\t\t\tint currentDepth) throws YAMLException {\n\t\tif (currentDepth >= MAX_DEPTH) {\n\t\t\tthrow new YAMLException(String.format(\"Schema extensions recursion depth limit(%d) reached.\", MAX_DEPTH));\n\t\t}\n\n\t\tif (!CollectionUtils.isEmpty(schema.getExtensions())) {\n\t\t\tObject paramSource = schema.getExtensions().get(DEFINED_EXTENSION);\n\t\t\tif (paramSource instanceof String && String.valueOf(paramSource).equals(EXTENSION_USER_SOURCE)) {\n\t\t\t\tString type = schema.getType();\n\t\t\t\t// 防止用户使用 \"token\" 类型的参数\n\t\t\t\tif (StringUtils.isNotBlank(type) && TOKEN_TYPE.equals(type)) {\n\t\t\t\t\tthrow new YAMLException(\"Type \\\"token\\\" is not allowed.\");\n\t\t\t\t}\n\n\t\t\t\tApiParameter param = new ApiParameter();\n\t\t\t\tparam.setKey(schemaField);\n\t\t\t\tparam.setType(type);\n\t\t\t\tparam.setDescription(schema.getDescription());\n\t\t\t\tresultList.add(param);\n\t\t\t}\n\t\t}","sourceCodeStart":576,"sourceCodeEnd":612,"githubUrl":"https://github.com/alibaba/spring-ai-alibaba/blob/f82da0b50f35744c13968191be2b1cd2452ef550/spring-ai-alibaba-admin/spring-ai-alibaba-admin-server-core/src/main/java/com/alibaba/cloud/ai/studio/core/utils/api/OpenApiUtils.java#L576-L612","documentation":"checkSchemaExtension() recursively expands OpenAPI schema extensions ($ref-style defined extension) while building output parameters; to prevent runaway recursion from circular schema references it enforces MAX_DEPTH and throws YAMLException when the depth limit is reached.","triggerScenarios":"Importing an OpenAPI spec whose schema extensions reference each other cyclically (A -> B -> A) or nest beyond MAX_DEPTH levels, during parseRestfulMethod output-parameter extraction.","commonSituations":"Recursive/circular models in specs (tree nodes, linked lists); deeply nested generated DTOs; specs where $ref-like extension chains were not resolved before import.","solutions":["Break the circular reference in the OpenAPI spec — inline one level or split the recursive model into shallower objects","Flatten deeply nested response models into fewer levels before importing","Increase MAX_DEPTH in OpenApiUtils if legitimately deep schemas must be supported (watch memory/stack)"],"exampleFix":"// before: Node -> children -> Node (circular)\n// after\nNode:\n  type: object\n  properties:\n    children:\n      type: array\n      items:\n        type: object\n        properties:\n          id: {type: string}","handlingStrategy":"validation","validationCode":"// detect circular schema extension references before import\nSet<String> visited = new HashSet<>();\nDeque<Schema<?>> stack = new ArrayDeque<>(List.of(rootSchema));\nwhile (!stack.isEmpty()) {\n    Schema<?> s = stack.pop();\n    if (!visited.add(System.identityHashCode(s) + \":\" + s.getType())) {\n        throw new IllegalArgumentException(\"Circular schema extension detected\");\n    }\n    if (s.getProperties() != null) stack.addAll(s.getProperties().values());\n}","typeGuard":null,"tryCatchPattern":"try {\n    OpenApiUtils.parseSchemaToForm(spec);\n} catch (YAMLException e) {\n    if (e.getMessage().contains(\"recursion depth limit\")) {\n        // locate the circular/nested model and flatten it before re-import\n    }\n}","preventionTips":["Avoid recursive self-referencing models in imported specs","Cap DTO nesting depth by design convention","Report the offending schema path in import tooling","Inline one or two levels of deeply nested models before import"],"tags":["openapi","recursion","validation","java"],"backgroundTag":"schema-validation-failed","analyzedSha":"f82da0b50f35744c13968191be2b1cd2452ef550","analyzedAt":"2026-09-09T15:32:42.421Z","contentChangedAt":"2026-09-09T15:32:42.421Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}