{"record":{"id":"6ea8f8d183b189b3","repo":"floci-io/floci","slug":"keygroupalreadyexists","errorCode":"KeyGroupAlreadyExists","errorMessage":"A key group with this name already exists.","messagePattern":"A key group with this name already exists\\.","errorType":"exception","errorClass":"AwsException","httpStatus":409,"severity":"error","filePath":"src/main/java/io/github/hectorvent/floci/services/cloudfront/CloudFrontService.java","lineNumber":1096,"sourceCode":"                    \"PreconditionFailed\",\n                    \"The precondition in one or more request-header fields evaluated to false.\",\n                    412);\n        }\n        if (keyGroupInUse(id)) {\n            throw new AwsException(\n                    \"ResourceInUse\",\n                    \"Cannot delete this resource because it is in use.\",\n                    409);\n        }\n        keyGroupStore.delete(id);\n    }\n\n    private void validateUniqueKeyGroupName(String name, String excludedId) {\n        boolean duplicate = keyGroupStore.scan(group -> true).stream()\n                .anyMatch(group -> !Objects.equals(excludedId, group.getId())\n                        && Objects.equals(name, group.getName()));\n        if (duplicate) {\n            throw new AwsException(\n                    \"KeyGroupAlreadyExists\",\n                    \"A key group with this name already exists.\",\n                    409);\n        }\n    }\n\n    public List<KeyGroup> listKeyGroups(String marker, int maxItems) {\n        List<KeyGroup> all = new ArrayList<>(keyGroupStore.scan(k -> true));\n        all.sort((a, b) -> a.getId().compareTo(b.getId()));\n        return paginate(all, marker, maxItems, KeyGroup::getId);\n    }\n\n    private static void validatePublicKey(PublicKey key) {\n        if (key == null\n                || key.getCallerReference() == null\n                || key.getCallerReference().isBlank()\n                || key.getName() == null\n                || key.getName().isBlank()","sourceCodeStart":1078,"sourceCodeEnd":1114,"githubUrl":"https://github.com/floci-io/floci/blob/62ff490619e7bd3554597c28c704081b4c15add5/src/main/java/io/github/hectorvent/floci/services/cloudfront/CloudFrontService.java#L1078-L1114","documentation":"CloudFrontService.validateUniqueKeyGroupName throws KeyGroupAlreadyExists (HTTP 409) when another stored key group (excluding the current id during updates) already uses the same Name. CloudFront key group names are globally unique per account, and the emulator scans the key group store on CreateKeyGroup and UpdateKeyGroup to enforce it.","triggerScenarios":"CreateKeyGroup with a Name already taken by another group; UpdateKeyGroup renaming a group to an existing name. The scan excludes the updated group's own id, so keeping your name during update is safe.","commonSituations":"Re-running setup scripts without teardown, so the previous run's group persists; test fixtures with fixed names like \"default-kg\" colliding across test classes sharing emulator state.","solutions":["Use a unique Name per create (suffix with UUID or run id) or delete the existing group first.","On update, either keep the current Name or verify the target name is unused via ListKeyGroups.","Add teardown or unique naming to fixtures so reruns cannot collide."],"exampleFix":"// before\ncreateKeyGroup(\"kg\", keys); // ok\ncreateKeyGroup(\"kg\", otherKeys); // 409\n\n// after\ncreateKeyGroup(\"kg-\" + UUID.randomUUID(), keys);","handlingStrategy":"validation","validationCode":"boolean keyGroupNameTaken(CloudFrontClient client, String name, String excludeId) {\n    return client.listKeyGroups(r -> r.build()).keyGroupList().items().stream()\n            .anyMatch(g -> name.equals(g.keyGroup().name()) && !g.id().equals(excludeId));\n}","typeGuard":null,"tryCatchPattern":"try {\n    return client.createKeyGroup(r -> r.keyGroupConfig(cfg));\n} catch (KeyGroupAlreadyExists e) {\n    // either reuse the existing group or retry with a suffixed unique name\n}","preventionTips":["Generate unique group names per run (append UUID or timestamp).","Delete fixture groups in teardown so reruns start clean.","Check ListKeyGroups before creating with a fixed name."],"tags":["cloudfront","key-group","uniqueness","conflict","aws-emulator"],"backgroundTag":null,"analyzedSha":"62ff490619e7bd3554597c28c704081b4c15add5","analyzedAt":"2026-08-14T14:25:23.764Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}