{"record":{"id":"b630fbd179a3165a","repo":"floci-io/floci","slug":"trailalreadyexistsexception","errorCode":"TrailAlreadyExistsException","errorMessage":"Trail {} already exists.","messagePattern":"Trail (.+?) already exists\\.","errorType":"exception","errorClass":"AwsException","httpStatus":400,"severity":"error","filePath":"src/main/java/io/github/hectorvent/floci/services/cloudtrail/CloudTrailService.java","lineNumber":70,"sourceCode":"                new TypeReference<Map<String, CloudTrailEntry>>() {});\n        this.regionResolver = regionResolver;\n        this.iamService = iamService;\n        this.mapper = mapper;\n    }\n\n    // --- Control plane ---\n\n    public Trail createTrail(String region, String name, String s3BucketName, String s3KeyPrefix,\n                             String snsTopicArn, boolean includeGlobalServiceEvents,\n                             boolean isMultiRegionTrail, boolean enableLogFileValidation,\n                             boolean isOrganizationTrail) {\n        validateTrailName(name);\n        if (s3BucketName == null || s3BucketName.isEmpty()) {\n            throw new AwsException(\"S3BucketDoesNotExistException\", \"S3 bucket name is required.\", 400);\n        }\n        String key = regionKey(region, name);\n        if (store.get(key).isPresent()) {\n            throw new AwsException(\"TrailAlreadyExistsException\",\n                    \"Trail \" + name + \" already exists.\", 400);\n        }\n        String arn = AwsArnUtils.Arn.of(\"cloudtrail\", region, regionResolver.getAccountId(),\n                \"trail/\" + name).toString();\n        Trail trail = new Trail(\n                name, arn, s3BucketName, s3KeyPrefix, snsTopicArn,\n                includeGlobalServiceEvents, isMultiRegionTrail, region,\n                enableLogFileValidation, false, false, isOrganizationTrail);\n        store.put(key, new CloudTrailEntry(trail, List.of(), false, null, null));\n        return trail;\n    }\n\n    public void deleteTrail(String region, String trailNameOrArn) {\n        Trail trail = findTrailOrThrow(region, trailNameOrArn);\n        store.delete(regionKey(trail.homeRegion(), trail.name()));\n        pendingRecordsByTrail.keySet().removeIf(k -> k.trailName().equals(trail.name()));\n    }\n","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/floci-io/floci/blob/62ff490619e7bd3554597c28c704081b4c15add5/src/main/java/io/github/hectorvent/floci/services/cloudtrail/CloudTrailService.java#L52-L88","documentation":"Thrown by CreateTrail when a trail with the same name already exists in the same region. Trails are keyed region:name (regionKey), and the duplicate check runs after name and bucket validation. AWS behaves the same: trail names are unique per region.","triggerScenarios":"Running CreateTrail twice with the same Name in one region — e.g. a setup script that is not idempotent, or a re-deploy after a partial failure that already created the trail.","commonSituations":"Bootstrap scripts run on every boot; state drift where the tool believes the trail does not exist (DescribeTrails filtering bug); parallel provisioning jobs racing to create the same trail.","solutions":["DescribeTrails first and skip creation if the name already exists in the region.","If the existing trail is stale, DeleteTrail before recreating.","Make bootstrap idempotent: create-if-absent instead of unconditional create."],"exampleFix":"// before\nclient.createTrail(b -> b.name(\"audit\").s3BucketName(bucket));\n\n// after\nboolean exists = client.describeTrails().trailList().stream()\n    .anyMatch(t -> t.name().equals(\"audit\"));\nif (!exists) {\n    client.createTrail(b -> b.name(\"audit\").s3BucketName(bucket));\n}","handlingStrategy":"validation","validationCode":"boolean exists = client.describeTrails().trailList().stream()\n    .anyMatch(t -> t.name().equals(name) && t.homeRegion().equals(region));\nif (!exists) client.createTrail(req);","typeGuard":null,"tryCatchPattern":"try {\n    client.createTrail(req);\n} catch (TrailAlreadyExistsException e) {\n    // adopt the existing trail: update its settings instead of creating\n}","preventionTips":["Make trail provisioning idempotent with describe-then-create.","On partial setup failures, check DescribeTrails before re-running bootstrap."],"tags":["aws","cloudtrail","duplicate","conflict","idempotency"],"backgroundTag":null,"analyzedSha":"62ff490619e7bd3554597c28c704081b4c15add5","analyzedAt":"2026-08-14T14:25:23.764Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}