iflytek/astron-agent · error · BusinessException
TOOLBOX_CANNOT_DELETE_RELATED_WORKFLOW
TOOLBOX_CANNOT_DELETE_RELATED_WORKFLOW
Error message
BusinessException(ResponseEnum.TOOLBOX_CANNOT_DELETE_RELATED_WORKFLOW)
What it means
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.
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.
Example fix
// before
toolBoxService.deleteTool(toolId); // fails while workflows reference it
// after
// 1. remove/detach the tool from every workflow referencing it
// 2. then delete
long refs = flowToolRelMapper.selectCount(
Wrappers.lambdaQuery(FlowToolRel.class).eq(FlowToolRel::getToolId, toolId));
if (refs == 0) {
toolBoxService.deleteTool(toolId);
} Defensive patterns
Strategy: validation
Validate before calling
long flowRefs = flowToolRelMapper.selectCount(
Wrappers.lambdaQuery(FlowToolRel.class).eq(FlowToolRel::getToolId, toolId));
if (flowRefs > 0) { /* block delete; list blocking workflows to the user */ } Try / catch
try {
toolBoxService.deleteTool(id);
} catch (BusinessException e) {
if ("TOOLBOX_CANNOT_DELETE_RELATED_WORKFLOW".equals(e.getCode())) {
// surface list of workflows using this tool
}
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- TOOLBOX_CANNOT_DELETE_RELATED
- DATABASE_DELETE_FAILED_CITED
- 8514
- REPO_DELETE_FAILED_BOT_USED
- RPA_IS_USAGE
AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12).
Data as JSON: /api/errors/e7f5afd662568347.
Report an issue: GitHub.
Appendix: source
Thrown at console/backend/toolkit/src/main/java/com/iflytek/astron/console/toolkit/service/tool/ToolBoxService.java:441
@Transactional
public Object deleteTool(Long id) {
ToolBox toolBox = getById(id);
if (toolBox == null) {
throw new BusinessException(ResponseEnum.TOOLBOX_NOT_EXIST_DELETE);
}
dataPermissionCheckTool.checkToolBelong(toolBox);
// Delete draft tools directly
if (toolBox.getStatus().equals(0)) {
toolBox.setDeleted(true);
toolBox.setUpdateTime(new Timestamp(System.currentTimeMillis()));
updateById(toolBox);
return ApiResult.success();
}
long flowListCount = flowToolRelMapper.selectCount(Wrappers.lambdaQuery(FlowToolRel.class).eq(FlowToolRel::getToolId, toolBox.getToolId()));
if (flowListCount > 0) {
throw new BusinessException(ResponseEnum.TOOLBOX_CANNOT_DELETE_RELATED_WORKFLOW);
}
long modelListCount = botToolRelService.count(Wrappers.lambdaQuery(BotToolRel.class).eq(BotToolRel::getToolId, toolBox.getToolId()));
if (modelListCount > 0) {
throw new BusinessException(ResponseEnum.TOOLBOX_CANNOT_DELETE_RELATED);
}
toolBoxMapper.update(null, new UpdateWrapper<ToolBox>().lambda()
.set(ToolBox::getDeleted, true)
.set(ToolBox::getUpdateTime, new Timestamp(System.currentTimeMillis()))
.eq(ToolBox::getToolId, toolBox.getToolId()));
String paramStr = "?app_id=" + commonConfig.getAppId() + "&tool_ids=" + toolBox.getToolId();
ToolResp toolDelResp = toolServiceCallHandler.toolDelete(paramStr);
toolServiceCallHandler.dealResult(toolDelResp);
return ApiResult.success();
}
View on GitHub (pinned to 5e758547a8)