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
- Pick a different repo name, or reuse the existing repo instead of creating a new one (list repos by name first).
- Check for an existing repo before creating: query repo by (userId or spaceId, name, deleted=0) in the client and update instead of create.
- If the duplicate is a leftover from a failed earlier attempt, delete/rename the old repo then retry.
- 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
- Check name availability client-side before submitting create.
- Debounce/disable the create button to prevent double submits.
- On retry-after-timeout, query by name first instead of blindly re-creating.
- Add a DB unique constraint on (scope, name, deleted) to make uniqueness race-proof.
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)