iflytek/astron-agent · warning · BusinessException

REPO_NAME_DUPLICATE

REPO_NAME_DUPLICATE

Error message

ResponseEnum.REPO_NAME_DUPLICATE

What it means

RepoService.validateRepoNameUnique() enforces that knowledge-base repo names are unique per owner: when spaceId is null it checks (userId, name, deleted=0), otherwise (spaceId, name, deleted=0). If getOnly finds an existing non-deleted repo with the same name it throws BusinessException(REPO_NAME_DUPLICATE), called from createRepo.

Solutions

  1. Pick a different repo name, or reuse the existing repo instead of creating a new one (list repos by name first).
  2. Check for an existing repo before creating: query repo by (userId or spaceId, name, deleted=0) in the client and update instead of create.
  3. If the duplicate is a leftover from a failed earlier attempt, delete/rename the old repo then retry.
  4. Guard against race conditions by adding a unique DB constraint on (space_id/user_id, name, deleted) and handling the constraint violation gracefully.

Example fix

// before
repoService.createRepo(repoVO); // throws REPO_NAME_DUPLICATE

// after
Repo existing = repoService.getOnly(Wrappers.lambdaQuery(Repo.class)
        .eq(Repo::getSpaceId, spaceId)
        .eq(Repo::getName, repoVO.getName())
        .eq(Repo::getDeleted, 0));
if (existing != null) {
    // reuse existing.getId() or prompt the user for a new name
} else {
    repoService.createRepo(repoVO);
}
Defensive patterns

Strategy: validation

Validate before calling

Repo existing = repoService.getOnly(Wrappers.lambdaQuery(Repo.class)
        .eq(spaceId != null, Repo::getSpaceId, spaceId)
        .eq(spaceId == null, Repo::getUserId, UserInfoManagerHandler.getUserId())
        .eq(Repo::getName, name)
        .eq(Repo::getDeleted, 0));
if (existing != null) { /* reuse existing or ask for a new name */ }

Type guard

boolean repoNameTaken(String name, Long spaceId) {
    return repoService.getOnly(Wrappers.lambdaQuery(Repo.class)
        .eq(spaceId != null, Repo::getSpaceId, spaceId)
        .eq(spaceId == null, Repo::getUserId, UserInfoManagerHandler.getUserId())
        .eq(Repo::getName, name)
        .eq(Repo::getDeleted, 0)) != null;
}

Try / catch

try {
    repoService.createRepo(repoVO);
} catch (BusinessException e) {
    if (ResponseEnum.REPO_NAME_DUPLICATE.getCode().equals(e.getCode())) {
        // prompt user for a different name or reuse the existing repo
    } else { throw e; }
}

Prevention

When it happens

Trigger: createRepo is called with a name that already exists for the same user (no spaceId) or within the same space: user retries a create after a timeout not knowing the first succeeded, re-creating a repo deleted only logically elsewhere, importing/copying a repo without renaming, or concurrent creates of the same name racing past the check.

Common situations: Double-clicking 'Create' in the UI; automation scripts re-running create on retry; switching between personal and space scopes and reusing the same name; soft-deleted rows with deleted=0 check interacting with restore flows.

Related errors


AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12). Data as JSON: /api/errors/10ac9a98790b02c1. Report an issue: GitHub.

Appendix: source

Thrown at console/backend/toolkit/src/main/java/com/iflytek/astron/console/toolkit/service/repo/RepoService.java:170

        String ragflowDatasetId = null;
        if (ProjectContent.FILE_SOURCE_RAG_FLOW_RAG_STR.equals(repoVO.getTag())) {
            String datasetName = buildRagflowDatasetName(repoVO.getName(), coreRepoId);
            ragflowDatasetId = knowledgeV2ServiceCallHandler.createRagflowDataset(datasetName, repoVO.getName());
        }

        return self.persistRepo(repoVO, spaceId, coreRepoId, ragflowDatasetId);
    }

    /** Reject duplicate repo names in the current personal or space scope. */
    private void validateRepoNameUnique(RepoVO repoVO, Long spaceId) {
        Repo existRepo;
        if (spaceId == null) {
            existRepo = this.getOnly(Wrappers.lambdaQuery(Repo.class).eq(Repo::getUserId, UserInfoManagerHandler.getUserId()).eq(Repo::getName, repoVO.getName()).eq(Repo::getDeleted, 0));
        } else {
            existRepo = this.getOnly(Wrappers.lambdaQuery(Repo.class).eq(Repo::getSpaceId, spaceId).eq(Repo::getName, repoVO.getName()).eq(Repo::getDeleted, 0));
        }
        if (existRepo != null) {
            throw new BusinessException(ResponseEnum.REPO_NAME_DUPLICATE);
        }
    }

    /** Reject unsupported RAG tags. */
    private void validateTag(String tag) {
        if (!ProjectContent.isCbgRagCompatible(tag) && !ProjectContent.isAiuiRagCompatible(tag)) {
            throw new BusinessException(ResponseEnum.REPO_TYPE_NOT_MATCH);
        }
    }

    /** Ragflow-RAG always uses a server-generated core repo id. */
    private String resolveCoreRepoId(RepoVO repoVO) {
        if (ProjectContent.FILE_SOURCE_RAG_FLOW_RAG_STR.equals(repoVO.getTag())) {
            return UUID.randomUUID().toString().replace("-", "");
        }
        if (StringUtils.isEmpty(repoVO.getOuterRepoId())) {
            return UUID.randomUUID().toString().replace("-", "");
        }

View on GitHub (pinned to 5e758547a8)