iflytek/astron-agent · error · BusinessException
REPO_DELETE_FAILED_BOT_USED
REPO_DELETE_FAILED_BOT_USED
Error message
ResponseEnum.REPO_DELETE_FAILED_BOT_USED
What it means
BusinessException REPO_DELETE_FAILED_BOT_USED is thrown by RepoService when attempting to soft-delete a repository (knowledge/repo entity) that is still referenced by at least one bot via the bot_repo_rel relation. The service counts BotRepoRel rows by coreRepoId and refuses deletion if any binding exists, because removing the repo would break bots that depend on it. It is a deliberate referential-integrity guard, not a system fault.
Solutions
- Find the bots using the repo (query BotRepoRel by repoId / coreRepoId) and detach the repo from each bot via the bot edit UI or the bot-repo unbind API.
- Re-run the delete once the relation count is 0.
- If relations are stale (bots already deleted), clean up orphan BotRepoRel rows, then delete the repo.
- If deletion should proceed anyway, first remove bindings programmatically in the same transaction before calling delete.
Example fix
// before repoService.deleteRepo(repoId); // throws REPO_DELETE_FAILED_BOT_USED // after botRepoRelService.remove(Wrappers.lambdaQuery(BotRepoRel.class).eq(BotRepoRel::getRepoId, repo.getCoreRepoId())); repoService.deleteRepo(repoId);
Defensive patterns
Strategy: try-catch
Validate before calling
long bound = botRepoRelService.count(Wrappers.lambdaQuery(BotRepoRel.class).eq(BotRepoRel::getRepoId, coreRepoId));
if (bound > 0) { /* detach bindings or abort */ } Try / catch
try {
repoService.deleteRepo(repoId);
} catch (BusinessException e) {
if ("REPO_DELETE_FAILED_BOT_USED".equals(e.getCode())) {
List<BotRepoRel> rels = botRepoRelService.list(...);
// prompt user to detach bots, then retry
} else throw e;
} Prevention
- List bot bindings in the UI before enabling the delete button; disable it when count > 0.
- Clean up bot-repo relations when deleting bots.
- In bulk-delete scripts, unbind relations in the same transaction before delete.
When it happens
Trigger: Calling the repo delete API (RepoService.deleteRepo, around RepoService.java:941) for a repo where `botRepoRelService.count(eq BotRepoRel::getRepoId, repo.getCoreRepoId()) > 0`, after the repo-belong permission check passes.
Common situations: Users try to delete a knowledge base / repo that is attached to one or more agents (bots) in the console; cleanup scripts that delete repos in bulk without first unbinding them from bots; stale bot-repo relations left over from deleted bots that block deletion.
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
- 8514
- DATABASE_DELETE_FAILED_CITED
- RPA_IS_USAGE
- TOOLBOX_CANNOT_DELETE_RELATED_WORKFLOW
- TOOLBOX_CANNOT_DELETE_RELATED
AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12).
Data as JSON: /api/errors/9518d2c717a687bd.
Report an issue: GitHub.
Appendix: source
Thrown at console/backend/toolkit/src/main/java/com/iflytek/astron/console/toolkit/service/repo/RepoService.java:941
* in use by bots
*/
@Transactional
public Object deleteRepo(Long id, String tag, HttpServletRequest request) {
// Check if tag equals Spark tag
if (ProjectContent.isSparkRagCompatible(tag)) {
log.info("Using Spark deletion logic");
return deleteXinghuoDataset(request, id.toString());
}
Repo repo = this.getById(id);
if (repo == null) {
throw new BusinessException(ResponseEnum.REPO_NOT_EXIST);
}
dataPermissionCheckTool.checkRepoBelong(repo);
long modelListCount = botRepoRelService.count(Wrappers.lambdaQuery(BotRepoRel.class).eq(BotRepoRel::getRepoId, repo.getCoreRepoId()));
if (modelListCount > 0) {
throw new BusinessException(ResponseEnum.REPO_DELETE_FAILED_BOT_USED);
}
repo.setDeleted(true);
this.updateById(repo);
// Metering rollback
List<FileInfoV2> fileInfos = fileInfoV2Mapper.getFileInfoV2ByRepoId(repo.getId());
for (FileInfoV2 fileInfoV2 : fileInfos) {
fileInfoV2Service.fileCostRollback(fileInfoV2.getUuid());
}
RepoVO repoVO = new RepoVO();
repoVO.setId(id);
repoVO.setOperType(ProjectContent.REPO_STATUS_DELETE);
return this.updateRepoStatus(repoVO);
}
// private JSONObject getKnowledgeQueryObject(String group, Integer topN, String query) {View on GitHub (pinned to 5e758547a8)