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
- Retry the request after a short delay — the error message explicitly advises this and the condition is transient.
- Enable namespace.lock.switch (apollo biz config) consistently across all admin service instances so that the locking flow is deterministic.
- If the error is persistent rather than transient, check for orphaned/rolled-back NamespaceLock rows in the database and verify transaction integrity.
- 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
- Enable namespace.lock.switch consistently across all admin service instances for deterministic locking.
- Serialize concurrent writes to the same namespace from the same integration to avoid lock contention.
- Monitor for persistent lock-check failures which indicate transaction-rollback issues.
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
- namespace:%s is modified by %s
- The App Id of path variable and request body is different
- can not delete default cluster!
- The maximum number of items (%s) for this namespace has been
- Comment item's key or value should be blank.
AI-assisted analysis of apolloconfig/apollo@d95fc18d11 (2026-08-14).
Data as JSON: /api/errors/60271c68e5101062.
Report an issue: GitHub.