floci-io/floci · error · AwsException

PublicKeyInUse

PublicKeyInUse

Error message

The specified public key is in use.

What it means

CloudFrontService.deletePublicKey throws PublicKeyInUse (HTTP 409) when publicKeyInUse(id) finds the key still referenced by some stored resource (for example a distribution configuration referencing it). CloudFront refuses to delete keys that configurations depend on, and the emulator mirrors that guard before removing the key from the store.

Source

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

                    400);
        }
        updated.setId(id);
        updated.setCreatedTime(existing.getCreatedTime());
        updated.setEtag(UUID.randomUUID().toString());
        publicKeyStore.put(id, updated);
        return updated;
    }

    public synchronized void deletePublicKey(String id, String ifMatch) {
        PublicKey existing = getPublicKey(id);
        if (!existing.getEtag().equals(ifMatch)) {
            throw new AwsException(
                    "PreconditionFailed",
                    "The precondition in one or more request-header fields evaluated to false.",
                    412);
        }
        if (publicKeyInUse(id)) {
            throw new AwsException(
                    "PublicKeyInUse", "The specified public key is in use.", 409);
        }
        publicKeyStore.delete(id);
    }

    public List<PublicKey> listPublicKeys(String marker, int maxItems) {
        List<PublicKey> all = new ArrayList<>(publicKeyStore.scan(k -> true));
        all.sort((a, b) -> a.getId().compareTo(b.getId()));
        return paginate(all, marker, maxItems, PublicKey::getId);
    }

    /**
     * Resolves the PEM public key for a {@code Key-Pair-Id} used to sign a request, but only when that
     * public key is a member of one of the supplied key groups. Returns {@code null} when the key is
     * unknown or is not a member of any of those groups — i.e. it is not a trusted signer.
     */
    public String trustedPublicKeyPem(String keyPairId, List<String> keyGroupIds) {
        if (keyPairId == null || keyGroupIds == null || keyGroupIds.isEmpty()) {

View on GitHub (pinned to 62ff490619)

Solutions

  1. Delete or update every distribution that references the key first, then delete the key.
  2. Before deleting, scan ListDistributions for configurations referencing the key id and clean them up.
  3. Make teardown order reverse of creation: distributions → key groups → public keys.

Example fix

// before
deletePublicKey(keyId); // 409 while a distribution references it

// after
for (Distribution d : distributionsReferencing(keyId)) {
    deleteDistribution(d.getId());
}
deletePublicKey(keyId);
Defensive patterns

Strategy: try-catch

Validate before calling

boolean publicKeyReferenced(CloudFrontClient client, String keyId) {
    return client.listDistributions(r -> r.build()).distributionList().items().stream()
            .anyMatch(d -> distributionReferencesKey(d, keyId));
}

Try / catch

try {
    client.deletePublicKey(r -> r.id(keyId).ifMatch(etag));
} catch (PublicKeyInUse e) {
    // find and remove/ delete referencing distributions, then retry delete with a fresh etag
}

Prevention

When it happens

Trigger: DeletePublicKey while any distribution's config still references the key id — e.g. deleting immediately after CreateDistribution succeeded, or after re-creating a distribution that re-attached the key.

Common situations: Teardown deleting resources in creation order (key before distribution); tests that recreate distributions between runs; forgetting that updated distributions may reintroduce references.

Related errors


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