floci-io/floci · error · AwsException

ChangeSetNotFoundException

ChangeSetNotFoundException

Error message

ChangeSet [{}] does not exist

What it means

DescribeChangeSet found the stack but its changeSets map has no entry under the resolved change-set name. AWS returns ChangeSetNotFoundException for this exact case. Names are resolved via resolveChangeSetName (which may normalize 'arn'-style inputs to the suffix), so a mismatch after resolution also lands here.

Source

Thrown at src/main/java/io/github/hectorvent/floci/services/cloudformation/CloudFormationService.java:192

        cs.setChangeSetType(changeSetType != null ? changeSetType : "CREATE");
        cs.setTemplateBody(resolvedTemplate);
        cs.setParameters(parameters);
        cs.setCapabilities(capabilities);
        cs.setStatus("CREATE_COMPLETE");
        cs.setExecutionStatus("AVAILABLE");

        stack.getChangeSets().put(changeSetName, cs);
        persistStack(stack);
        return cs;
    }

    // ── DescribeChangeSet ─────────────────────────────────────────────────────

    public ChangeSet describeChangeSet(String stackName, String changeSetName, String region) {
        Stack stack = getStackOrThrow(stackName, region);
        ChangeSet cs = stack.getChangeSets().get(resolveChangeSetName(changeSetName));
        if (cs == null) {
            throw new AwsException("ChangeSetNotFoundException",
                    "ChangeSet [" + changeSetName + "] does not exist", 400);
        }
        return cs;
    }

    // ── ExecuteChangeSet ──────────────────────────────────────────────────────

    public Future<?> executeChangeSet(String stackName, String changeSetName, String region) {
        return executeChangeSet(stackName, changeSetName, region, regionResolver.getAccountId());
    }

    /**
     * Executes a change set, provisioning its resources into {@code accountId}'s namespace.
     *
     * <p>Provisioning runs on a background executor thread that has no inherited request scope, so
     * the downstream service calls would otherwise fall back to the default account. The resources
     * are materialized under a synthetic request scope bound to {@code accountId} so a single-stack
     * deployment lands in the caller's account, and a StackSet instance lands in its target account.

View on GitHub (pinned to 62ff490619)

Solutions

  1. List the stack's change sets first (aws cloudformation list-change-sets --stack-name s) and use the exact ChangeSetName shown.
  2. Confirm you are targeting the right stack — the change set must be looked up on the stack it belongs to.
  3. If the change set was executed and cleaned up, create a new one before describing.

Example fix

# before
aws cloudformation describe-change-set --stack-name app --change-set-name deploy-v2  # deleted
# after
aws cloudformation list-change-sets --stack-name app
aws cloudformation describe-change-set --stack-name app --change-set-name <exact-name-from-list>
Defensive patterns

Strategy: try-catch

Validate before calling

sets = cfn.listChangeSets(StackName=stack)['Summaries']
known = {s['ChangeSetName'] for s in sets}
if csName not in known: raise SystemExit(f'{csName} not on {stack}; have {known}')

Type guard

const hasChangeSet = (summaries, name) => summaries.some(s => s.ChangeSetName === name || s.ChangeSetId === name);

Try / catch

try {
    cfn.describeChangeSet(StackName=s, ChangeSetName=cs);
} catch (e) {
    if (e.code === 'ChangeSetNotFound') { /* recreate set */ }
    else throw e;
}

Prevention

When it happens

Trigger: aws cloudformation describe-change-set --stack-name s --change-set-name cs where cs was never created on s, was already executed-and-removed, or its arn suffix differs from the supplied name.

Common situations: CI pipeline describing a change set after another job deleted it; passing the full ARN when the emulator stored a short name (or vice versa); wrong stack name so the lookup hits an unrelated stack.

Related errors


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