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

  1. Check isAppIdUnique(appId) before calling save().
  2. If the app already exists, retrieve and use it instead of creating a new one.
  3. Ensure app-creation requests are not retried on timeout without first checking existence.
  4. 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

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


AI-assisted analysis of apolloconfig/apollo@d95fc18d11 (2026-08-14). Data as JSON: /api/errors/522c1cb1d361ae4b. Report an issue: GitHub.