{"record":{"id":"d3a0547dc1307585","repo":"apolloconfig/apollo","slug":"accesskeys-count-limit-exceeded","errorCode":null,"errorMessage":"AccessKeys count limit exceeded","messagePattern":"AccessKeys count limit exceeded","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/AccessKeyService.java","lineNumber":51,"sourceCode":"  private static final int ACCESSKEY_COUNT_LIMIT = 5;\n\n  private final AccessKeyRepository accessKeyRepository;\n  private final AuditService auditService;\n\n  public AccessKeyService(AccessKeyRepository accessKeyRepository, AuditService auditService) {\n    this.accessKeyRepository = accessKeyRepository;\n    this.auditService = auditService;\n  }\n\n  public List<AccessKey> findByAppId(String appId) {\n    return accessKeyRepository.findByAppId(appId);\n  }\n\n  @Transactional\n  public AccessKey create(String appId, AccessKey entity) {\n    long count = accessKeyRepository.countByAppId(appId);\n    if (count >= ACCESSKEY_COUNT_LIMIT) {\n      throw new BadRequestException(\"AccessKeys count limit exceeded\");\n    }\n\n    entity.setId(0L);\n    entity.setAppId(appId);\n    entity.setDataChangeLastModifiedBy(entity.getDataChangeCreatedBy());\n    AccessKey accessKey = accessKeyRepository.save(entity);\n\n    auditService.audit(AccessKey.class.getSimpleName(), accessKey.getId(), Audit.OP.INSERT,\n        accessKey.getDataChangeCreatedBy());\n\n    return accessKey;\n  }\n\n  @Transactional\n  public AccessKey update(String appId, AccessKey entity) {\n    long id = entity.getId();\n    String operator = entity.getDataChangeLastModifiedBy();\n","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/apolloconfig/apollo/blob/d95fc18d112589efc09ddcbe1507047584d55251/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/AccessKeyService.java#L33-L69","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: blindly create keys\naccessKeyApi.create(appId, newKey);\n\n// after: clean up old disabled keys before creating new ones\nList<AccessKeyDTO> keys = accessKeyApi.findByAppId(appId);\nfor (AccessKeyDTO key : keys) {\n    if (!key.isEnabled()) {\n        accessKeyApi.delete(appId, key.getId()); // frees a slot\n    }\n}\naccessKeyApi.create(appId, newKey); // now succeeds","handlingStrategy":"validation","validationCode":"// Check current key count before creating\nList<AccessKey> existing = accessKeyService.findByAppId(appId);\nif (existing.size() >= 5) {\n    // delete unused/disabled keys first\n    existing.stream().filter(k -> !k.isEnabled()).forEach(k ->\n        accessKeyService.delete(appId, k.getId(), operator));\n}\naccessKeyService.create(appId, newKey);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["access-key","limit","security","bad-request","apollo-biz"],"backgroundTag":null,"analyzedSha":"d95fc18d112589efc09ddcbe1507047584d55251","analyzedAt":"2026-08-14T04:00:05.477Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}