floci-io/floci · error · AwsException

NoSuchFunctionExists

NoSuchFunctionExists

Error message

The specified function does not exist.

What it means

CloudFrontService.describeFunction throws NoSuchFunctionExists (HTTP 404) when no function is stored under the given Name, or when a Stage parameter was supplied and the stored function's stage does not match it. It is the standard not-found signal for DescribeFunction and also the lookup primitive reused by updateFunction, publishFunction, and deleteFunction, so those operations surface it too when the name is wrong.

Source

Thrown at src/main/java/io/github/hectorvent/floci/services/cloudfront/CloudFrontService.java:786

    // ── CloudFront Functions ──────────────────────────────────────────────────

    public synchronized CloudFrontFunction createFunction(CloudFrontFunction fn) {
        fn.setStage("DEVELOPMENT");
        fn.setStatus("UNPUBLISHED");
        fn.setEtag(UUID.randomUUID().toString());
        fn.setCreatedTime(Instant.now());
        fn.setLastModifiedTime(Instant.now());
        functionStore.put(fn.getName(), fn);
        return fn;
    }

    public CloudFrontFunction describeFunction(String name, String stage) {
        CloudFrontFunction fn = functionStore.get(name).orElseThrow(() ->
                new AwsException("NoSuchFunctionExists",
                        "The specified function does not exist.", 404));
        if (stage != null && !stage.isEmpty() && !fn.getStage().equals(stage)) {
            throw new AwsException("NoSuchFunctionExists",
                    "The specified function does not exist.", 404);
        }
        return fn;
    }

    public synchronized CloudFrontFunction updateFunction(String name, String ifMatch,
                                                          CloudFrontFunction updated) {
        CloudFrontFunction existing = describeFunction(name, null);
        if (!existing.getEtag().equals(ifMatch)) {
            throw new AwsException("InvalidIfMatchVersion",
                    "The If-Match version is missing or not valid for the resource.", 400);
        }
        updated.setName(name);
        updated.setStage(existing.getStage());
        updated.setStatus(existing.getStatus());
        updated.setEtag(UUID.randomUUID().toString());
        updated.setCreatedTime(existing.getCreatedTime());
        updated.setLastModifiedTime(Instant.now());

View on GitHub (pinned to 62ff490619)

Solutions

  1. Create the function first with CreateFunction and verify success before calling Describe/Update/Publish.
  2. If querying with Stage, either omit it or match the real stage: use "DEVELOPMENT" before publishFunction, "LIVE" after.
  3. Pass the plain function Name (not the ARN) exactly as it was set at creation.
  4. If the function should exist, check ListFunctions to confirm what names and stages are actually stored.

Example fix

// before
cloudFront.describeFunction(req -> req.name("my-fn").stage("LIVE")); // 404 pre-publish

// after
cloudFront.describeFunction(req -> req.name("my-fn")); // or publish first, then query LIVE
Defensive patterns

Strategy: try-catch

Validate before calling

boolean functionExists(CloudFrontClient client, String name) {
    return client.listFunctions(r -> r.build()).functionList().items().stream()
            .anyMatch(f -> f.name().equals(name));
}

Try / catch

try {
    return client.describeFunction(r -> r.name(name).stage(stage));
} catch (NoSuchFunctionExists e) {
    if (stage != null) { // maybe just wrong stage; retry without it
        return client.describeFunction(r -> r.name(name));
    }
    throw e;
}

Prevention

When it happens

Trigger: DescribeFunction with a name never created, deleted, or misspelled; or DescribeFunction with Stage="LIVE" when the function is still in "DEVELOPMENT" stage (publishFunction is what promotes it to LIVE). Calling UpdateFunction/PublishFunction/DeleteFunction on a nonexistent name hits the same orElseThrow.

Common situations: Reading a function before it is published and expecting LIVE metadata; using the ARN or alias instead of the bare Name; test ordering where the create call failed earlier so later steps 404; emulator storage reset between test phases losing in-memory functions.

Related errors


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