apolloconfig/apollo · error · BadRequestException
AccessKeys count limit exceeded
Error message
AccessKeys count limit exceeded
What it means
A BadRequestException (HTTP 400) thrown from AccessKeyService.create() when the number of existing access keys for an appId has reached the hardcoded limit ACCESSKEY_COUNT_LIMIT (5). Apollo caps the number of access keys per app to prevent unbounded key proliferation. The count includes soft-deleted keys that have not been physically removed if the count query counts all rows (the check uses accessKeyRepository.countByAppId before the new key is saved).
Source
Thrown at apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/AccessKeyService.java:51
private static final int ACCESSKEY_COUNT_LIMIT = 5;
private final AccessKeyRepository accessKeyRepository;
private final AuditService auditService;
public AccessKeyService(AccessKeyRepository accessKeyRepository, AuditService auditService) {
this.accessKeyRepository = accessKeyRepository;
this.auditService = auditService;
}
public List<AccessKey> findByAppId(String appId) {
return accessKeyRepository.findByAppId(appId);
}
@Transactional
public AccessKey create(String appId, AccessKey entity) {
long count = accessKeyRepository.countByAppId(appId);
if (count >= ACCESSKEY_COUNT_LIMIT) {
throw new BadRequestException("AccessKeys count limit exceeded");
}
entity.setId(0L);
entity.setAppId(appId);
entity.setDataChangeLastModifiedBy(entity.getDataChangeCreatedBy());
AccessKey accessKey = accessKeyRepository.save(entity);
auditService.audit(AccessKey.class.getSimpleName(), accessKey.getId(), Audit.OP.INSERT,
accessKey.getDataChangeCreatedBy());
return accessKey;
}
@Transactional
public AccessKey update(String appId, AccessKey entity) {
long id = entity.getId();
String operator = entity.getDataChangeLastModifiedBy();
View on GitHub (pinned to d95fc18d11)
Solutions
- Delete unused or disabled access keys to free up slots (must disable first, then delete — see error [10]).
- Audit existing keys via AccessKeyService.findByAppId(appId) and remove obsolete ones.
- If 5 keys are genuinely all in active use, reconsider the key management strategy or consolidate.
- Implement a key lifecycle policy: create new, rotate clients, disable old, delete old.
Example fix
// before: blindly create keys
accessKeyApi.create(appId, newKey);
// after: clean up old disabled keys before creating new ones
List<AccessKeyDTO> keys = accessKeyApi.findByAppId(appId);
for (AccessKeyDTO key : keys) {
if (!key.isEnabled()) {
accessKeyApi.delete(appId, key.getId()); // frees a slot
}
}
accessKeyApi.create(appId, newKey); // now succeeds Defensive patterns
Strategy: validation
Validate before calling
// Check current key count before creating
List<AccessKey> existing = accessKeyService.findByAppId(appId);
if (existing.size() >= 5) {
// delete unused/disabled keys first
existing.stream().filter(k -> !k.isEnabled()).forEach(k ->
accessKeyService.delete(appId, k.getId(), operator));
}
accessKeyService.create(appId, newKey); Prevention
- Implement a key lifecycle policy: create → rotate → disable → delete.
- Regularly audit and clean up disabled access keys.
- Never create keys without a deletion plan for the old ones.
When it happens
Trigger: POST to create a new AccessKey for an appId that already has 5 (or more) access keys. The count is taken before insert; if count >= 5, the create is rejected.
Common situations: Key rotation without deleting old keys; abandoned/disabled keys left in the system; a provisioning script that creates keys on each deployment without cleanup; testing that creates many keys without removing prior ones.
Related errors
- AccessKey should disable first
- value too long. length limit:%s
- key too long. length limit:%s
- The maximum number of items (%s) for this namespace has been
- cluster not unique
AI-assisted analysis of apolloconfig/apollo@d95fc18d11 (2026-08-14).
Data as JSON: /api/errors/d3a0547dc1307585.
Report an issue: GitHub.