floci-io/floci · error · AwsException

TooManyTagsException

TooManyTagsException

Error message

Certificate cannot have more than " + MAX_TAGS + " tags

What it means

ACM TooManyTagsException (HTTP 400) thrown by AcmService.addTagsToCertificate when merging the new tags onto the certificate's existing tags yields more than MAX_TAGS (50) distinct keys. The limit is checked after the merge, so it is the combined total, not just the new batch, that matters.

Source

Thrown at src/main/java/io/github/hectorvent/floci/services/acm/AcmService.java:433

        // Return certificate with encrypted private key
        Certificate exportCert = new Certificate();
        exportCert.setCertificateBody(cert.getCertificateBody());
        exportCert.setCertificateChain(cert.getCertificateChain());
        exportCert.setPrivateKey(encryptedKey);
        return exportCert;
    }

    // ============ Tagging Operations ============

    public void addTagsToCertificate(String certificateArn, Map<String, String> tags, String region) {
        Certificate cert = getCertificateByArn(certificateArn, region);
        validateTags(tags);

        Map<String, String> currentTags = cert.getTags() != null ? new HashMap<>(cert.getTags()) : new HashMap<>();
        currentTags.putAll(tags);

        if (currentTags.size() > MAX_TAGS) {
            throw new AwsException("TooManyTagsException",
                "Certificate cannot have more than " + MAX_TAGS + " tags", 400);
        }

        cert.setTags(currentTags);
        store.put(regionKey(region, cert.extractCertificateId()), cert);
    }

    public Map<String, String> listTagsForCertificate(String certificateArn, String region) {
        Certificate cert = getCertificateByArn(certificateArn, region);
        return cert.getTags() != null ? new HashMap<>(cert.getTags()) : new HashMap<>();
    }

    public void removeTagsFromCertificate(String certificateArn, List<Map<String, String>> tagSpecs, String region) {
        Certificate cert = getCertificateByArn(certificateArn, region);
        Map<String, String> currentTags = cert.getTags() != null ? new HashMap<>(cert.getTags()) : new HashMap<>();

        for (Map<String, String> spec : tagSpecs) {
            String key = spec.get("Key");

View on GitHub (pinned to 62ff490619)

Solutions

  1. Reduce the request: tag fewer keys, overwrite existing keys instead of adding new ones (same key replaces, doesn't count twice), or removeTagsFromCertificate first
  2. Check current usage: listTagsForCertificate and compute 50 - current size before adding
  3. Consolidate tag keys (e.g. one 'owner' key instead of owner-team + owner-user) if a fixed large tag set is mandated

Example fix

// before
acm.addTagsToCertificate(r -> r.certificateArn(arn).tags(allSixtyTags));

// after
var current = acm.listTagsForCertificate(r -> r.certificateArn(arn)).tags();
int room = 50 - current.size();
var toAdd = newTags.entrySet().stream()
    .filter(e -> !current.containsKey(e.getKey()))
    .limit(Math.max(0, room))
    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
if (!toAdd.isEmpty()) acm.addTagsToCertificate(r -> r.certificateArn(arn).tags(toAdd));
Defensive patterns

Strategy: validation

Validate before calling

var current = acm.listTagsForCertificate(r -> r.certificateArn(arn)).tags();
int newKeys = (int) newTags.keySet().stream().filter(k -> !current.containsKey(k)).count();
if (current.size() + newKeys > 50) throw new IllegalArgumentException("tag budget exceeded");

Try / catch

try {
    acm.addTagsToCertificate(r -> r.certificateArn(arn).tags(newTags));
} catch (TooManyTagsException e) {
    // removeTagsFromCertificate for stale keys, then retry with a reduced set
}

Prevention

When it happens

Trigger: acm.addTagsToCertificate on a cert that already has N tags where N + (number of new distinct keys not already present) > 50. Adding a large tag map in one call, or repeated additive tagging without removal, crosses the threshold.

Common situations: Bulk-tagging scripts that append ownership metadata per team/environment until the cap is hit; copying a 60-key corporate tag policy onto ACM certs; orchestration layers ( Terraform/CFN) applying global tags on top of service-specific ones.

Understand the failure class

Related errors


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