quarkusio/quarkus · error · SpiffeConnectionException

X.509-SVID response from SPIRE agent contains a non-X.509 ce

Error message

X.509-SVID response from SPIRE agent contains a non-X.509 certificate in ${description}: ${certClassName}

What it means

While iterating certificates parsed from the DER bytes, an element was not an instance of X509Certificate. The Java CertificateFactory can yield other certificate types (e.g. X509CRL or legacy cert classes), and the SPIFFE client only supports X.509, so it rejects the payload naming the offending class.

Source

Thrown at extensions/spiffe-client/runtime/src/main/java/io/quarkus/spiffe/client/runtime/internal/SpiffeClientImpl.java:347

        var keyMaterial = new WorkloadCertificateChainImpl(unmodifiableList(certChain), privateKey);
        var trustMaterial = new WorkloadTrustBundleImpl(unmodifiableList(trustBundle));
        return new WorkloadCertificateDocumentImpl(protoSpiffeId, keyMaterial, trustMaterial);
    }

    private static List<X509Certificate> parseCertificates(byte[] derBytes, String description)
            throws SpiffeConnectionException {
        if (derBytes.length == 0) {
            throw new SpiffeConnectionException("X.509-SVID response contains empty " + description);
        }
        try {
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            Collection<?> certs = cf.generateCertificates(new ByteArrayInputStream(derBytes));
            List<X509Certificate> result = new ArrayList<>(certs.size());
            for (var cert : certs) {
                if (cert instanceof X509Certificate x509) {
                    result.add(x509);
                } else {
                    throw new SpiffeConnectionException(
                            "X.509-SVID response from SPIRE agent contains a non-X.509 certificate in "
                                    + description + ": " + cert.getClass().getName());
                }
            }
            return result;
        } catch (Exception e) {
            throw new SpiffeConnectionException(
                    "X.509-SVID response from SPIRE agent contains an invalid " + description, e);
        }
    }

    private static List<String> certsToPem(List<X509Certificate> certs) {
        try {
            List<String> result = new ArrayList<>(certs.size());
            for (X509Certificate cert : certs) {
                result.add(toPem("CERTIFICATE", cert.getEncoded()));
            }
            return unmodifiableList(result);

View on GitHub (pinned to e1c734241f)

Solutions

  1. Restart/upgrade the SPIRE agent and re-fetch; valid SPIRE data is always X.509.
  2. Inspect the bytes (openssl x509 -inform DER -in bundle.pem) to see what was actually delivered.
  3. Remove/replace custom security providers that alter CertificateFactory behavior.
  4. If a mock is used in tests, populate fields with genuine DER-encoded X.509 certificates.
Defensive patterns

Strategy: try-catch

Validate before calling

// sanity-check the delivered DER parses as X.509:
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Collection<?> c = cf.generateCertificates(new ByteArrayInputStream(derBytes));
c.forEach(x -> { if (!(x instanceof X509Certificate)) throw new IllegalStateException(); });

Try / catch

try {
    doc = client.getWorkloadCertificate();
} catch (SpiffeConnectionException e) {
    if (e.getMessage().contains("non-X.509 certificate")) {
        // inspect custom providers / mock data producing non-X.509 certs
        throw new IllegalStateException("Non-X.509 data from Workload API: " + e.getMessage(), e);
    } else throw e;
}

Prevention

When it happens

Trigger: parseCertificates called with chain or bundle bytes whose generated certificate collection contains a non-X.509 element (cert instanceof X509Certificate fails).

Common situations: A custom security provider returning a different certificate implementation; corrupted or foreign DER data in the bundle field; test mocks feeding arbitrary bytes; extremely old agents embedding legacy formats.

Understand the failure class

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/9388628b2b776435. Report an issue: GitHub.