apolloconfig/apollo · critical · ServiceException
appId not unique
Error message
appId not unique
What it means
A ServiceException (HTTP 500) thrown from AppService.save() when an app with the given appId already exists. The uniqueness check isAppIdUnique() queries appRepository.findByAppId(appId) and a non-null result means the appId is taken. Since appId is the primary business key across all of Apollo, a collision is a significant data-integrity event.
Source
Thrown at apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/AppService.java:81
public List<App> findAll(Pageable pageable) {
Page<App> page = appRepository.findAll(pageable);
return page.getContent();
}
public List<App> findByName(String name) {
return appRepository.findByName(name);
}
public App findOne(String appId) {
return appRepository.findByAppId(appId);
}
@Transactional
@ApolloAuditLog(type = OpType.CREATE, name = "App.create")
public App save(App entity) {
if (!isAppIdUnique(entity.getAppId())) {
throw new ServiceException("appId not unique");
}
entity.setId(0);// protection
App app = appRepository.save(entity);
auditService.audit(App.class.getSimpleName(), app.getId(), Audit.OP.INSERT,
app.getDataChangeCreatedBy());
return app;
}
@Transactional
@ApolloAuditLog(type = OpType.UPDATE, name = "App.update")
public void update(App app) {
String appId = app.getAppId();
App managedApp = appRepository.findByAppId(appId);
if (managedApp == null) {
throw BadRequestException.appNotExists(appId);View on GitHub (pinned to d95fc18d11)
Solutions
- Check isAppIdUnique(appId) before calling save().
- If the app already exists, retrieve and use it instead of creating a new one.
- Ensure app-creation requests are not retried on timeout without first checking existence.
- Use a deterministic, unique appId generation strategy to avoid collisions.
Example fix
// before: unconditional creation
appService.save(app);
// after: idempotent creation
if (appService.isAppIdUnique(app.getAppId())) {
appService.save(app);
} else {
app = appService.findOne(app.getAppId());
} Defensive patterns
Strategy: validation
Validate before calling
// Check appId uniqueness before saving
if (appService.isAppIdUnique(app.getAppId())) {
return appService.save(app);
} else {
// app already exists — return existing instead of creating
return appService.findOne(app.getAppId());
} Prevention
- Always call isAppIdUnique() before AppService.save() to avoid the ServiceException.
- Do not retry app-creation on client timeout without first checking existence.
- Use a deterministic appId to avoid accidental collisions.
When it happens
Trigger: POST /apps (AppService.save) with an appId that already exists in the App table. The error fires before any insert is attempted.
Common situations: Retried app-creation request after a client timeout (the first request succeeded); two environments or operators creating the same appId; a migration or seed script re-run; appId collision due to a naming convention conflict.
Related errors
- appnamespace not unique
- cluster not unique
- namespace not unique
- Check lock for %s failed, please retry.
- The App Id of path variable and request body is different
AI-assisted analysis of apolloconfig/apollo@d95fc18d11 (2026-08-14).
Data as JSON: /api/errors/522c1cb1d361ae4b.
Report an issue: GitHub.