{"record":{"id":"eeb679ac18bf4bd2","repo":"floci-io/floci","slug":"toomanytagsexception","errorCode":"TooManyTagsException","errorMessage":"Certificate cannot have more than \" + MAX_TAGS + \" tags","messagePattern":"Certificate cannot have more than \" \\+ MAX_TAGS \\+ \" tags","errorType":"http","errorClass":"AwsException","httpStatus":400,"severity":"error","filePath":"src/main/java/io/github/hectorvent/floci/services/acm/AcmService.java","lineNumber":433,"sourceCode":"        // Return certificate with encrypted private key\n        Certificate exportCert = new Certificate();\n        exportCert.setCertificateBody(cert.getCertificateBody());\n        exportCert.setCertificateChain(cert.getCertificateChain());\n        exportCert.setPrivateKey(encryptedKey);\n        return exportCert;\n    }\n\n    // ============ Tagging Operations ============\n\n    public void addTagsToCertificate(String certificateArn, Map<String, String> tags, String region) {\n        Certificate cert = getCertificateByArn(certificateArn, region);\n        validateTags(tags);\n\n        Map<String, String> currentTags = cert.getTags() != null ? new HashMap<>(cert.getTags()) : new HashMap<>();\n        currentTags.putAll(tags);\n\n        if (currentTags.size() > MAX_TAGS) {\n            throw new AwsException(\"TooManyTagsException\",\n                \"Certificate cannot have more than \" + MAX_TAGS + \" tags\", 400);\n        }\n\n        cert.setTags(currentTags);\n        store.put(regionKey(region, cert.extractCertificateId()), cert);\n    }\n\n    public Map<String, String> listTagsForCertificate(String certificateArn, String region) {\n        Certificate cert = getCertificateByArn(certificateArn, region);\n        return cert.getTags() != null ? new HashMap<>(cert.getTags()) : new HashMap<>();\n    }\n\n    public void removeTagsFromCertificate(String certificateArn, List<Map<String, String>> tagSpecs, String region) {\n        Certificate cert = getCertificateByArn(certificateArn, region);\n        Map<String, String> currentTags = cert.getTags() != null ? new HashMap<>(cert.getTags()) : new HashMap<>();\n\n        for (Map<String, String> spec : tagSpecs) {\n            String key = spec.get(\"Key\");","sourceCodeStart":415,"sourceCodeEnd":451,"githubUrl":"https://github.com/floci-io/floci/blob/62ff490619e7bd3554597c28c704081b4c15add5/src/main/java/io/github/hectorvent/floci/services/acm/AcmService.java#L415-L451","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Reduce the request: tag fewer keys, overwrite existing keys instead of adding new ones (same key replaces, doesn't count twice), or removeTagsFromCertificate first","Check current usage: listTagsForCertificate and compute 50 - current size before adding","Consolidate tag keys (e.g. one 'owner' key instead of owner-team + owner-user) if a fixed large tag set is mandated"],"exampleFix":"// before\nacm.addTagsToCertificate(r -> r.certificateArn(arn).tags(allSixtyTags));\n\n// after\nvar current = acm.listTagsForCertificate(r -> r.certificateArn(arn)).tags();\nint room = 50 - current.size();\nvar toAdd = newTags.entrySet().stream()\n    .filter(e -> !current.containsKey(e.getKey()))\n    .limit(Math.max(0, room))\n    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));\nif (!toAdd.isEmpty()) acm.addTagsToCertificate(r -> r.certificateArn(arn).tags(toAdd));","handlingStrategy":"validation","validationCode":"var current = acm.listTagsForCertificate(r -> r.certificateArn(arn)).tags();\nint newKeys = (int) newTags.keySet().stream().filter(k -> !current.containsKey(k)).count();\nif (current.size() + newKeys > 50) throw new IllegalArgumentException(\"tag budget exceeded\");","typeGuard":null,"tryCatchPattern":"try {\n    acm.addTagsToCertificate(r -> r.certificateArn(arn).tags(newTags));\n} catch (TooManyTagsException e) {\n    // removeTagsFromCertificate for stale keys, then retry with a reduced set\n}","preventionTips":["Check the 50-tag budget via listTagsForCertificate before every add","Prefer overwriting existing keys over introducing new ones","Remove obsolete tags when re-tagging instead of only adding"],"tags":["acm","tagging","limits","too-many-tags","aws"],"backgroundTag":null,"analyzedSha":"62ff490619e7bd3554597c28c704081b4c15add5","analyzedAt":"2026-08-14T14:25:23.764Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}