{"record":{"id":"0170cb1984bd07bd","repo":"alibaba/spring-ai-alibaba","slug":"toolnotfound","errorCode":"ToolNotFound","errorMessage":"Tool can not be found.","messagePattern":"Tool can not be found\\.","errorType":"error_code","errorClass":"BizException","httpStatus":404,"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":344,"sourceCode":"\t\t\tthrow new BizException(ErrorCode.CREATE_TOOL_ERROR.toError(), e);\n\t\t}\n\t}\n\n\t/**\n\t * Updates an existing tool\n\t * @param tool Updated tool information\n\t */\n\t@Override\n\tpublic void updateTool(Tool tool) {\n\t\ttry {\n\t\t\tRequestContext context = RequestContextHolder.getRequestContext();\n\n\t\t\tString toolName = tool.getName();\n\t\t\tString pluginId = tool.getPluginId();\n\n\t\t\tToolEntity entity = getToolById(context.getWorkspaceId(), tool.getToolId());\n\t\t\tif (entity == null) {\n\t\t\t\tthrow new BizException(ErrorCode.TOOL_NOT_FOUND.toError());\n\t\t\t}\n\n\t\t\tPlugin plugin = getPlugin(pluginId);\n\n\t\t\t// check if tool name exists\n\t\t\tToolEntity toolEntity = getToolByName(context.getWorkspaceId(), plugin.getPluginId(), toolName);\n\t\t\tif (toolEntity != null && !toolEntity.getId().equals(entity.getId())) {\n\t\t\t\tthrow new BizException(ErrorCode.TOOL_NAME_EXISTS.toError());\n\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\"));","sourceCodeStart":326,"sourceCodeEnd":362,"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#L326-L362","documentation":"Not-found guard raised in PluginServiceImpl.updateTool. Before modifying a tool, the service looks it up via getToolById(workspaceId, toolId); when no matching tool entity exists in that workspace it throws a BizException with the TOOL_NOT_FOUND error code, since updates require an existing target. Typically caused by a stale or invalid toolId after the plugin was resynced or the tool was deleted. Callers should handle it as a 404-style business error.","triggerScenarios":"Calling PluginServiceImpl.updateTool with a toolId that was deleted, never existed, was created in a different workspace, or with an incorrect RequestContext workspaceId so the workspace-scoped lookup misses.","commonSituations":"Stale tool ID cached in client code after the tool was deleted; switching workspaces/environments while reusing IDs; typos in IDs passed from configuration.","solutions":["Confirm the toolId exists by listing tools in the target workspace (getTools/plugin tool list) before updating.","Verify RequestContext.getWorkspaceId() matches the workspace that owns the tool.","Re-fetch the tool to obtain a fresh ID if it was deleted and recreated.","Handle BizException(ToolNotFound) in the caller with a clear user-facing message."],"exampleFix":"// before: blind update with stale id\ntool.setToolId(staleId);\ntoolService.updateTool(context, tool);\n\n// after: check existence first\nif (toolService.getTool(toolId) == null) { /* handle missing */ }\ntoolService.updateTool(context, tool);","handlingStrategy":"validation","validationCode":"// existence pre-check scoped to the workspace\nToolEntity existing = toolService.getToolByName(workspaceId, pluginId, tool.getName());\n// or list tools and assert the id is present before updating\nboolean exists = toolService.getTools(workspaceId, pluginId)\n        .stream().anyMatch(t -> toolId.equals(t.getId()));\nif (!exists) { throw new IllegalStateException(\"tool \" + toolId + \" not in workspace\"); }","typeGuard":null,"tryCatchPattern":"try {\n    toolService.updateTool(context, tool);\n} catch (BizException e) {\n    if (\"ToolNotFound\".equals(e.getCode())) {\n        // refresh local cache of tool ids; do not retry blindly\n    } else { throw e; }\n}","preventionTips":["Never hard-code tool IDs in config; resolve them by name per workspace.","Refresh cached tool IDs after any delete/import operation.","Keep RequestContext workspace consistent across a request lifecycle.","Treat tool IDs as environment-specific, not portable between dev/staging/prod."],"tags":["not-found","plugin-tools","workspace-scope"],"backgroundTag":"record-not-found","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"}