floci-io/floci · error · AwsException

ResourceInUseException

ResourceInUseException

Error message

Certificate " + certificateArn + " is in use by: " + String.join(", ", cert.getInUseBy())

What it means

ACM ResourceInUseException (HTTP 409) thrown by AcmService.deleteCertificate when the certificate's inUseBy list is non-empty. Floci tracks which resources (e.g. load balancers, CloudFront distributions) reference a certificate; ACM refuses deletion while the certificate is attached, mirroring AWS behavior.

Source

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

        if (token == null || token.isEmpty()) return null;
        try {
            String json = new String(Base64.getDecoder().decode(token), StandardCharsets.UTF_8);
            // Simple JSON parsing without Jackson dependency in this method
            int start = json.indexOf("\"lastArn\":\"") + 11;
            int end = json.indexOf("\"", start);
            return json.substring(start, end);
        } catch (Exception e) {
            throw new AwsException("InvalidNextTokenException", "Invalid pagination token", 400);
        }
    }

    // ============ DeleteCertificate ============

    public void deleteCertificate(String certificateArn, String region) {
        Certificate cert = getCertificateByArn(certificateArn, region);

        if (cert.getInUseBy() != null && !cert.getInUseBy().isEmpty()) {
            throw new AwsException("ResourceInUseException",
                "Certificate " + certificateArn + " is in use by: " + String.join(", ", cert.getInUseBy()), 409);
        }

        String storageKey = regionKey(region, cert.extractCertificateId());
        store.delete(storageKey);
        LOG.infov("Deleted certificate: {0}", certificateArn);
    }

    // ============ ImportCertificate ============

    public Certificate importCertificate(String certificatePem, String privateKeyPem, String chainPem,
                                          String existingArn, Map<String, String> tags, String region) {
        logSecurityWarningOnce();
        // Parse and validate certificate
        X509Certificate x509Cert;
        try {
            x509Cert = certificateGenerator.parseCertificate(certificatePem);
            certificateGenerator.validateCertificate(x509Cert);

View on GitHub (pinned to 62ff490619)

Solutions

  1. Read the error message — it lists exactly which resources hold the certificate
  2. Delete or detach the dependent resource(s) first (delete the ALB/CloudFront/stack), then retry deleteCertificate
  3. In CloudFormation scenarios, delete the stack that owns the certificate rather than calling deleteCertificate directly
  4. Make cleanup scripts order-independent: loop until deletions succeed or tolerate 409 with a retry budget

Example fix

// before
acm.deleteCertificate(r -> r.certificateArn(arn));

// after: release dependents first, then delete
// 1) delete stack / listener that references arn
// 2) optionally confirm: describeCertificate(arn).inUseBy() is empty
acm.deleteCertificate(r -> r.certificateArn(arn));
Defensive patterns

Strategy: try-catch

Validate before calling

var cert = acm.describeCertificate(r -> r.certificateArn(arn)).certificate();
if (cert.hasInUseBy() && !cert.inUseBy().isEmpty()) {
    throw new IllegalStateException("certificate still in use by " + cert.inUseBy());
}

Try / catch

try {
    acm.deleteCertificate(r -> r.certificateArn(arn));
} catch (ResourceInUseException e) {
    // parse the holders from e.getMessage(), delete them first, then retry once
}

Prevention

When it happens

Trigger: acm.deleteCertificate on an ARN whose Certificate.inUseBy contains at least one entry — i.e. some other emulated resource (ALB listener, CloudFront alias, API Gateway domain) still references the cert. The message enumerates the exact holders.

Common situations: Test teardown deleting certificates before the stacks that use them; CloudFormation stacks still ACTIVE referencing the cert via Fn::GetAtt/Ref; retrying a cleanup script out of order after a partial failure.

Understand the failure class

Related errors


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