{"record":{"id":"a2ed35d01379d07c","repo":"alibaba/spring-ai-alibaba","slug":"buildtoolschemaerror","errorCode":"BuildToolSchemaError","errorMessage":"Failed to build tool schema.","messagePattern":"Failed to build tool schema\\.","errorType":"error_code","errorClass":"BizException","httpStatus":400,"severity":"error","filePath":"spring-ai-alibaba-admin/spring-ai-alibaba-admin-server-core/src/main/java/com/alibaba/cloud/ai/studio/core/base/service/impl/PluginServiceImpl.java","lineNumber":295,"sourceCode":"\t\t\t}\n\n\t\t\tTool.ToolConfig config = tool.getConfig();\n\t\t\tList<ApiParameter> inputParams = config.getInputParams();\n\t\t\tif (!CollectionUtils.isEmpty(inputParams)) {\n\t\t\t\tfor (ApiParameter apiParameter : inputParams) {\n\t\t\t\t\tString location = apiParameter.getLocation();\n\t\t\t\t\tif (\"Get\".equals(config.getRequestMethod()) && location.equals(\"Body\")) {\n\t\t\t\t\t\tthrow new BizException(\n\t\t\t\t\t\t\t\tErrorCode.INVALID_PARAMS.toError(\"input_params\", \"Get method not support body params\"));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// convert to swagger yaml\n\t\t\tString yaml = OpenApiUtils.buildOpenAPIYaml(plugin, tool);\n\n\t\t\tif (StringUtils.isBlank(yaml) || !CollectionUtils.isEmpty(OpenApiUtils.parseOpenAPIObject(yaml))) {\n\t\t\t\tthrow new BizException(ErrorCode.BUILD_TOOL_SCHEMA_ERROR.toError());\n\t\t\t}\n\n\t\t\tString toolId = IdGenerator.idStr();\n\t\t\tToolEntity entity = BeanCopierUtils.copy(tool, ToolEntity.class);\n\t\t\tentity.setToolId(toolId);\n\t\t\tentity.setPluginId(tool.getPluginId());\n\t\t\tentity.setWorkspaceId(context.getWorkspaceId());\n\t\t\tentity.setConfig(JsonUtils.toJson(tool.getConfig()));\n\t\t\tentity.setApiSchema(yaml);\n\t\t\tentity.setStatus(ToolStatus.DRAFT);\n\t\t\tentity.setEnabled(false);\n\t\t\tentity.setTestStatus(ToolTestStatus.NOT_TEST);\n\n\t\t\tentity.setGmtCreate(new Date());\n\t\t\tentity.setGmtModified(new Date());\n\t\t\tentity.setCreator(context.getAccountId());\n\t\t\tentity.setModifier(context.getAccountId());\n","sourceCodeStart":277,"sourceCodeEnd":313,"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/base/service/impl/PluginServiceImpl.java#L277-L313","documentation":"Thrown by createTool when OpenApiUtils.buildOpenAPIYaml fails to produce a usable OpenAPI schema for the new tool: the generated YAML is blank or the generated document does not parse into a valid OpenAPI object. The library refuses to persist a tool whose API schema cannot be built or parsed, because the tool would be unusable at invocation time.","triggerScenarios":"Calling PluginServiceImpl.createTool with a Tool whose config (path, requestMethod, host/server URL, parameters) is incomplete or malformed so OpenApiUtils.buildOpenAPIYaml returns blank or OpenApiUtils.parseOpenAPIObject(yaml) returns a non-empty error list.","commonSituations":"Importing a plugin tool from a hand-written OpenAPI spec with a missing servers URL or invalid path; a request method/parameter combination that cannot be expressed in OpenAPI (e.g. GET with body params was not blocked upstream); YAML serialization producing empty output for edge-case configs.","solutions":["Validate the Tool config fields (name, description, path, requestMethod, server host URL) are populated and well-formed before calling createTool.","Remove request/parameter combos OpenAPI cannot express, e.g. body params on GET requests (see INVALID_PARAMS check).","Call OpenApiUtils.buildOpenAPIYaml/parseOpenAPIObject locally to see exactly what is blank or failing to parse.","Check server logs / exception cause chain for the underlying YAML generation or parsing exception."],"exampleFix":"// before: createTool with incomplete config\nTool tool = new Tool();\ntool.setName(\"weather\"); // no path, no requestMethod, no servers\ntoolService.createTool(context, tool);\n\n// after: fully populated config\nToolConfig config = new ToolConfig();\nconfig.setPath(\"/v1/weather\");\nconfig.setRequestMethod(\"GET\");\nconfig.setServiceGroup(\"https://api.example.com\");\nTool tool = new Tool();\ntool.setName(\"weather\");\ntool.setConfig(config);","handlingStrategy":"validation","validationCode":"// pre-check the schema before createTool\nString yaml = OpenApiUtils.buildOpenAPIYaml(plugin, tool);\nif (yaml == null || yaml.isBlank() || !OpenApiUtils.parseOpenAPIObject(yaml).isEmpty()) {\n    throw new IllegalArgumentException(\"tool config cannot produce a valid OpenAPI schema\");\n}\ntoolService.createTool(context, tool);","typeGuard":null,"tryCatchPattern":"try {\n    toolService.createTool(context, tool);\n} catch (BizException e) {\n    if (\"BuildToolSchemaError\".equals(e.getCode())) {\n        // show schema editor / config validation errors to the user\n    } else { throw e; }\n}","preventionTips":["Always populate path, requestMethod, and server URL in ToolConfig before creating tools.","Run buildOpenAPIYaml/parseOpenAPIObject in unit tests for every tool template you ship.","Never combine GET with Body parameters (they also trip INVALID_PARAMS).","Import only OpenAPI specs that pass a lint/parse step first."],"tags":["openapi","yaml","plugin-tools","validation"],"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"}