{"record":{"id":"e7f5afd662568347","repo":"iflytek/astron-agent","slug":"toolbox-cannot-delete-related-workflow","errorCode":"TOOLBOX_CANNOT_DELETE_RELATED_WORKFLOW","errorMessage":"BusinessException(ResponseEnum.TOOLBOX_CANNOT_DELETE_RELATED_WORKFLOW)","messagePattern":"BusinessException\\(ResponseEnum\\.TOOLBOX_CANNOT_DELETE_RELATED_WORKFLOW\\)","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":441,"sourceCode":"\n    @Transactional\n    public Object deleteTool(Long id) {\n        ToolBox toolBox = getById(id);\n        if (toolBox == null) {\n            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","sourceCodeStart":423,"sourceCodeEnd":459,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/console/backend/toolkit/src/main/java/com/iflytek/astron/console/toolkit/service/tool/ToolBoxService.java#L423-L459","documentation":"ToolBoxService.deleteTool throws TOOLBOX_CANNOT_DELETE_RELATED_WORKFLOW when flowToolRelMapper.selectCount finds at least one FlowToolRel row referencing the tool's toolId. Published tools (status != 0) that are bound to one or more workflows are protected from deletion to avoid breaking those workflows. Deletion is refused as a referential-integrity guard.","triggerScenarios":"Calling deleteTool for a published tool whose toolId appears in the flow_tool_rel table; attempting to remove a tool currently used by any workflow (agent flow) in the space.","commonSituations":"User tries to clean up a tool still wired into live workflows; reorganization/deprecation of shared tools that multiple workflows depend on; automated garbage-collection of tools without checking references first.","solutions":["Find and remove the tool from all workflows that reference it, then retry deletion.","If workflows are obsolete, delete them first so their FlowToolRel rows are removed.","Check the flow_tool_rel table (toolId = the tool's toolId) to list blocking workflows.","Keep the tool if it is intentionally shared; deletion of shared published tools should be a deliberate workflow-migration task."],"exampleFix":"// before\ntoolBoxService.deleteTool(toolId); // fails while workflows reference it\n// after\n// 1. remove/detach the tool from every workflow referencing it\n// 2. then delete\nlong refs = flowToolRelMapper.selectCount(\n    Wrappers.lambdaQuery(FlowToolRel.class).eq(FlowToolRel::getToolId, toolId));\nif (refs == 0) {\n    toolBoxService.deleteTool(toolId);\n}","handlingStrategy":"validation","validationCode":"long flowRefs = flowToolRelMapper.selectCount(\n    Wrappers.lambdaQuery(FlowToolRel.class).eq(FlowToolRel::getToolId, toolId));\nif (flowRefs > 0) { /* block delete; list blocking workflows to the user */ }","typeGuard":null,"tryCatchPattern":"try {\n    toolBoxService.deleteTool(id);\n} catch (BusinessException e) {\n    if (\"TOOLBOX_CANNOT_DELETE_RELATED_WORKFLOW\".equals(e.getCode())) {\n        // surface list of workflows using this tool\n    }\n}","preventionTips":["Show dependent workflows in the delete confirmation dialog before deleting.","Detach tools from workflows as part of any tool-deprecation runbook.","Query flow_tool_rel before batch-deleting tools."],"tags":["tool-management","referential-integrity","workflow-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"}