floci-io/floci · error · AwsException

TrailNotFoundException

TrailNotFoundException

Error message

Unknown trail: {}

What it means

Thrown by findTrailOrThrow when no trail matches the given name or ARN. Lookup is region-scoped for names (regionKey) and ARN-based otherwise; a miss raises TrailNotFoundException. Note HTTP status is 400 here, whereas the AWS SDK maps TrailNotFoundException to 404-like semantics — SDK exception typing still works by error code.

Source

Thrown at src/main/java/io/github/hectorvent/floci/services/cloudtrail/CloudTrailService.java:464

            for (String k : store.keys()) {
                CloudTrailEntry entry = store.get(k).orElse(null);
                if (entry == null) continue;
                if (nameOrArn.equals(entry.trail().trailArn())) {
                    return entry.trail();
                }
            }
            return null;
        }
        // Name → region-scoped only (AWS resolves a name only in the current Region)
        return store.get(regionKey(region, nameOrArn))
                .map(CloudTrailEntry::trail)
                .orElse(null);
    }

    private Trail findTrailOrThrow(String region, String nameOrArn) {
        Trail t = findTrail(region, nameOrArn);
        if (t == null) {
            throw new AwsException("TrailNotFoundException",
                    "Unknown trail: " + nameOrArn, 400);
        }
        return t;
    }

    private static void validateTrailName(String name) {
        if (name == null || name.isEmpty()) {
            throw new AwsException("InvalidTrailNameException", "Trail name is required.", 400);
        }
        if (name.length() < 3) {
            throw new AwsException("InvalidTrailNameException",
                    "Trail name too short. Minimum allowed length: 3 characters.", 400);
        }
        if (name.length() > 128) {
            throw new AwsException("InvalidTrailNameException",
                    "Trail name too long. Maximum allowed length: 128 characters.", 400);
        }
        if (!Character.isLetterOrDigit(name.charAt(0))) {

View on GitHub (pinned to 62ff490619)

Solutions

  1. DescribeTrails to confirm the trail exists and note its HomeRegion.
  2. Verify the client is configured for the region where the trail was created.
  3. Copy the exact name/ARN from the create response or DescribeTrails output rather than reconstructing it.

Example fix

// before
client.deleteTrail(b -> b.name("audit-trail")); // wrong region client

// after
client = CloudTrailClient.builder().region(Region.US_EAST_1).build();
client.deleteTrail(b -> b.name("audit-trail"));
Defensive patterns

Strategy: try-catch

Validate before calling

boolean found = client.describeTrails().trailList().stream()
    .anyMatch(t -> nameOrArn.equals(t.name()) || nameOrArn.equals(t.trailARN()));
if (!found) throw new IllegalStateException("No trail '" + nameOrArn + "' in " + region);

Try / catch

try {
    client.deleteTrail(b -> b.name(name));
} catch (TrailNotFoundException e) {
    // already deleted (possibly in another region): treat as idempotent success
}

Prevention

When it happens

Trigger: DeleteTrail/UpdateTrail/StartLogging/StopLogging/GetTrailStatus/PutEventSelectors with a trail name that does not exist in the current region, or a typo'd/malformed ARN; also using a name scoped to a different region (names resolve only in their own region).

Common situations: Multi-region setups where the trail exists in us-east-1 but the client is pointed at another region; stale config after a trail was deleted; string interpolation that leaves a placeholder in the name.

Related errors


AI-assisted analysis of floci-io/floci@62ff490619 (2026-08-14). Data as JSON: /api/errors/38ecf9cf0ff62e13. Report an issue: GitHub.