{"record":{"id":"fce2645425bccca5","repo":"iflytek/astron-agent","slug":"toolbox-cannot-delete-related","errorCode":"TOOLBOX_CANNOT_DELETE_RELATED","errorMessage":"BusinessException(ResponseEnum.TOOLBOX_CANNOT_DELETE_RELATED)","messagePattern":"BusinessException\\(ResponseEnum\\.TOOLBOX_CANNOT_DELETE_RELATED\\)","errorType":"error_code","errorClass":"BusinessException","httpStatus":null,"severity":"error","filePath":"console/backend/toolkit/src/main/java/com/iflytek/astron/console/toolkit/service/tool/ToolBoxService.java","lineNumber":446,"sourceCode":"            throw new BusinessException(ResponseEnum.TOOLBOX_NOT_EXIST_DELETE);\n        }\n        dataPermissionCheckTool.checkToolBelong(toolBox);\n        // Delete draft tools directly\n        if (toolBox.getStatus().equals(0)) {\n            toolBox.setDeleted(true);\n            toolBox.setUpdateTime(new Timestamp(System.currentTimeMillis()));\n            updateById(toolBox);\n            return ApiResult.success();\n        }\n\n        long flowListCount = flowToolRelMapper.selectCount(Wrappers.lambdaQuery(FlowToolRel.class).eq(FlowToolRel::getToolId, toolBox.getToolId()));\n        if (flowListCount > 0) {\n            throw new BusinessException(ResponseEnum.TOOLBOX_CANNOT_DELETE_RELATED_WORKFLOW);\n        }\n\n        long modelListCount = botToolRelService.count(Wrappers.lambdaQuery(BotToolRel.class).eq(BotToolRel::getToolId, toolBox.getToolId()));\n        if (modelListCount > 0) {\n            throw new BusinessException(ResponseEnum.TOOLBOX_CANNOT_DELETE_RELATED);\n        }\n\n        toolBoxMapper.update(null, new UpdateWrapper<ToolBox>().lambda()\n                .set(ToolBox::getDeleted, true)\n                .set(ToolBox::getUpdateTime, new Timestamp(System.currentTimeMillis()))\n                .eq(ToolBox::getToolId, toolBox.getToolId()));\n\n        String paramStr = \"?app_id=\" + commonConfig.getAppId() + \"&tool_ids=\" + toolBox.getToolId();\n        ToolResp toolDelResp = toolServiceCallHandler.toolDelete(paramStr);\n        toolServiceCallHandler.dealResult(toolDelResp);\n        return ApiResult.success();\n    }\n\n    public Object debugTool(Long id, JSONObject reqData) {\n        ToolBox toolBox = getById(id);\n        if (toolBox == null) {\n            throw new BusinessException(ResponseEnum.TOOLBOX_NOT_EXIST);\n        }","sourceCodeStart":428,"sourceCodeEnd":464,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/console/backend/toolkit/src/main/java/com/iflytek/astron/console/toolkit/service/tool/ToolBoxService.java#L428-L464","documentation":"ToolBoxService.deleteTool throws TOOLBOX_CANNOT_DELETE_RELATED when botToolRelService.count finds at least one BotToolRel row referencing the tool's toolId, meaning the tool is used by one or more bots/agents (models). Like the workflow check, this blocks deletion of published tools that are still in use. The tool is only soft-deleted once no workflow or bot references remain.","triggerScenarios":"Calling deleteTool for a published tool bound to a bot via bot_tool_rel; deleting a tool that an agent configured as its tool/plugin; cleanup of tools still attached to any bot in the space.","commonSituations":"User unaware a production bot still uses the tool; batch tool removal scripts that skip bot-reference checks; environment cloning where bot-tool relations persist even though the UI no longer shows them.","solutions":["Detach the tool from all bots (update each bot's tool configuration) and retry deletion.","Query bot_tool_rel for the toolId to enumerate the blocking bots.","Delete or reconfigure obsolete bots that reference the tool first.","If the tool must go immediately, migrate bots to a replacement tool before deleting."],"exampleFix":"// before\ntoolBoxService.deleteTool(toolId); // blocked by bot references\n// after\nlong botRefs = botToolRelService.count(\n    Wrappers.lambdaQuery(BotToolRel.class).eq(BotToolRel::getToolId, toolId));\nif (botRefs == 0) {\n    toolBoxService.deleteTool(toolId);\n}","handlingStrategy":"validation","validationCode":"long botRefs = botToolRelService.count(\n    Wrappers.lambdaQuery(BotToolRel.class).eq(BotToolRel::getToolId, toolId));\nif (botRefs > 0) { /* block delete; list blocking bots to the user */ }","typeGuard":null,"tryCatchPattern":"try {\n    toolBoxService.deleteTool(id);\n} catch (BusinessException e) {\n    if (\"TOOLBOX_CANNOT_DELETE_RELATED\".equals(e.getCode())) {\n        // surface list of bots using this tool\n    }\n}","preventionTips":["Show dependent bots in the delete confirmation dialog.","Check bot_tool_rel before removing tools in automation.","Migrate bots to replacement tools before deleting shared tools."],"tags":["tool-management","referential-integrity","bot-dependency"],"backgroundTag":"invalid-state-transition","analyzedSha":"5e758547a83371a5a4b29dadf4ac03e8dd527635","analyzedAt":"2026-09-12T08:03:51.356Z","contentChangedAt":"2026-09-12T08:03:51.356Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}