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

  1. 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.
  2. Re-run the delete once the relation count is 0.
  3. If relations are stale (bots already deleted), clean up orphan BotRepoRel rows, then delete the repo.
  4. 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

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


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)