apereo/cas · error · BeanCreationException

Configuration element indicated an entityCertificate, but…

Error message

Configuration element indicated an entityCertificate, but multiple certificates were decoded

What it means

getEntityCertificate() decodes the resource referenced by entityResource and requires exactly one X509 certificate, because the entityCertificate configuration element models a single certificate. If X509Support.decodeCertificates() yields more than one certificate from that file, the bean creation is aborted with this BeanCreationException. This guards against ambiguous PEM bundles being silently treated as the single entity certificate.

Solutions

  1. Split the PEM file so the entityCertificate resource contains only the single entity (leaf) certificate block.
  2. Move the extra certificates into the certificateResources/CertificateFile element, which accepts multiple certificates for the chain.
  3. Extract just the first/leaf block with a text editor or: openssl x509 -in fullchain.pem -out leaf.pem.
  4. If multiple certs are intentional, use the multi-certificate configuration property instead of entityCertificate.

Example fix

# before: entityCertificate=file:/etc/cas/fullchain.pem  (leaf + intermediates)
# after
cas.authn.saml.idp.credential.entity-certificate=file:/etc/cas/idp-leaf.pem
cas.authn.saml.idp.credential.certificates=file:/etc/cas/intermediate.pem
Defensive patterns

Strategy: validation

Validate before calling

// pre-check the entity certificate resource yields exactly one cert
try (var is = entityResource.getInputStream()) {
    var certs = X509Support.decodeCertificates(is);
    if (certs.size() != 1) {
        throw new IllegalStateException("entityCertificate must contain exactly 1 certificate, found " + certs.size());
    }
}

Prevention

When it happens

Trigger: entityResource points to a file containing multiple certificates — typically a full-chain PEM (leaf + intermediates) or a concatenated .pem bundle — passed as the single entityCertificate element, decoded in getEntityCertificate().

Common situations: Downloading a cert chain from a CA (fullchain.pem from Let's Encrypt) and wiring it as entityCertificate; concatenating cert + CA cert into one file; exporting from a keystore into a multi-cert PEM; confusion between the single entityCertificate element and the certificates/CertificateFile list element which is meant for chains.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08). Data as JSON: /api/errors/7ef01ef398a8ed8a. Report an issue: GitHub.

Appendix: source

Thrown at support/cas-server-support-saml-core-api/src/main/java/org/apereo/cas/support/saml/util/credential/BasicX509CredentialFactoryBean.java:124

            credential.getKeyNames().addAll(this.keyNames);
        }

        return credential;
    }

    @Override
    public Class<?> getObjectType() {
        return BasicX509Credential.class;
    }

    private X509Certificate getEntityCertificate() {
        if (null == entityResource) {
            return null;
        }
        try {
            val certs = X509Support.decodeCertificates(entityResource.getInputStream());
            if (certs.size() > 1) {
                throw new BeanCreationException("Configuration element indicated an entityCertificate,"
                    + " but multiple certificates were decoded");
            }
            return certs.iterator().next();
        } catch (final Exception e) {
            throw new BeanCreationException("Could not decode provided Entity Certificate file "
                + entityResource.getDescription(), e);
        }
    }

    private List<X509Certificate> getCertificates() {
        if (certificateResources == null) {
            return new ArrayList<>();
        }

        val certificates = new LazyList<X509Certificate>();
        for (val r : certificateResources) {
            try (val is = r.getInputStream()) {
                certificates.addAll(X509Support.decodeCertificates(is));

View on GitHub (pinned to e7288fc434)