apolloconfig/apollo · error · ServiceException

Check lock for %s failed, please retry.

Error message

Check lock for %s failed, please retry.

What it means

A ServiceException (HTTP 500) thrown from NamespaceAcquireLockAspect.checkLock() when a namespace lock row is null after a failed concurrent insert. This occurs during the optimistic-locking namespace lock flow: two callers race to insert a NamespaceLock row; the loser catches DataIntegrityViolationException, re-queries the lock, and if it is STILL null (the winner's transaction was rolled back or the row was deleted), this error fires. It is inherently transient — the message itself says 'please retry.'

Source

Thrown at apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/aop/NamespaceAcquireLockAspect.java:158

        throw e;
      }
    } else {
      // check lock owner is current user
      checkLock(namespace, namespaceLock, currentUser);
    }
  }

  private void tryLock(long namespaceId, String user) {
    NamespaceLock lock = new NamespaceLock();
    lock.setNamespaceId(namespaceId);
    lock.setDataChangeCreatedBy(user);
    lock.setDataChangeLastModifiedBy(user);
    namespaceLockService.tryLock(lock);
  }

  private void checkLock(Namespace namespace, NamespaceLock namespaceLock, String currentUser) {
    if (namespaceLock == null) {
      throw new ServiceException(
          String.format("Check lock for %s failed, please retry.", namespace.getNamespaceName()));
    }

    String lockOwner = namespaceLock.getDataChangeCreatedBy();
    if (!lockOwner.equals(currentUser)) {
      throw new BadRequestException(
          "namespace:" + namespace.getNamespaceName() + " is modified by " + lockOwner);
    }
  }


}

View on GitHub (pinned to d95fc18d11)

Solutions

  1. Retry the request after a short delay — the error message explicitly advises this and the condition is transient.
  2. Enable namespace.lock.switch (apollo biz config) consistently across all admin service instances so that the locking flow is deterministic.
  3. If the error is persistent rather than transient, check for orphaned/rolled-back NamespaceLock rows in the database and verify transaction integrity.
  4. Reduce concurrent callers editing the same namespace by serializing writes at the application level.

Example fix

// before: fire-and-forget with no retry
openApi.createItem(appId, env, cluster, namespace, itemDTO);

// after: retry with backoff for transient ServiceException
int maxRetries = 3;
for (int i = 0; i <= maxRetries; i++) {
    try {
        openApi.createItem(appId, env, cluster, namespace, itemDTO);
        break;
    } catch (ServiceException e) {
        if (e.getMessage().contains("please retry") && i < maxRetries) {
            Thread.sleep(200L * (i + 1));
            continue;
        }
        throw e;
    }
}
Defensive patterns

Strategy: retry

Try / catch

// Retry with exponential backoff for transient lock race
int maxRetries = 3;
for (int attempt = 0; attempt <= maxRetries; attempt++) {
    try {
        openApi.createItem(appId, env, cluster, namespace, itemDTO);
        break;
    } catch (ServiceException e) {
        if (e.getMessage().contains("please retry") && attempt < maxRetries) {
            Thread.sleep(200L * (attempt + 1));
            continue;
        }
        throw e;
    }
}

Prevention

When it happens

Trigger: Two concurrent mutations (create/update/delete item, or change-set update) on the same namespace when namespace.lock.switch is enabled (bizConfig.isNamespaceLockSwitchOff() returns false). The first thread wins the INSERT; the second gets a unique-constraint violation, re-queries, and finds no row because the winner rolled back.

Common situations: High-concurrency edits to the same Apollo namespace from multiple portals or API clients; a previous edit transaction rolled back due to another validation failure, leaving no committed lock row; testing with parallel requests against a single namespace.

Related errors


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