quarkusio/quarkus · error · SpiffeConnectionException

X.509-SVID response from SPIRE agent has empty private key

Error message

X.509-SVID response from SPIRE agent has empty private key

What it means

The X.509-SVID contained an empty x509_svid_key field, i.e. no private key bytes accompanied the certificate chain. The client needs the private key to build a KeyPair/key material for mTLS, so an SVID without a key is unusable and rejected.

Source

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

        }
        return new WorkloadJsonWebTokenImpl(token, sub, Set.copyOf(audience), expiry);
    }

    private static WorkloadCertificateDocument toWorkloadCertificate(X509SVIDResponse response)
            throws SpiffeConnectionException {
        List<X509SVID> svids = response.getSvidsList();
        if (svids.isEmpty()) {
            throw new SpiffeConnectionException("X.509-SVID response from SPIRE agent contains no SVIDs");
        }
        X509SVID svid = svids.get(0);

        String protoSpiffeId = svid.getSpiffeId();
        SpiffeValidator.validateSpiffeId(protoSpiffeId);
        if (svid.getX509Svid().isEmpty()) {
            throw new SpiffeConnectionException("X.509-SVID response from SPIRE agent has empty certificate chain");
        }
        if (svid.getX509SvidKey().isEmpty()) {
            throw new SpiffeConnectionException("X.509-SVID response from SPIRE agent has empty private key");
        }
        if (svid.getBundle().isEmpty()) {
            throw new SpiffeConnectionException("X.509-SVID response from SPIRE agent has empty trust bundle");
        }

        List<X509Certificate> certChain = parseCertificates(svid.getX509Svid().toByteArray(), "certificate chain");
        if (certChain.isEmpty()) {
            throw new SpiffeConnectionException("X.509-SVID certificate chain is empty");
        }

        X509Certificate leaf = certChain.get(0);
        String sanSpiffeId = SpiffeValidator.validateLeaf(leaf);
        if (!protoSpiffeId.equals(sanSpiffeId)) {
            throw new SpiffeConnectionException(
                    "X.509-SVID proto SPIFFE ID does not match the leaf certificate URI SAN; proto: "
                            + protoSpiffeId + ", SAN: " + sanSpiffeId);
        }
        for (int i = 1; i < certChain.size(); i++) {

View on GitHub (pinned to e1c734241f)

Solutions

  1. Restart/upgrade the SPIRE agent so it serves complete SVIDs (cert + key + bundle).
  2. Confirm no intermediary (sidecar proxy, egress filter) strips protobuf fields.
  3. Re-request the SVID; transient truncation may resolve on retry.
  4. If using a mock/stub Workload API in tests, populate x509_svid_key with a valid PKCS8-encoded key.
Defensive patterns

Strategy: retry

Try / catch

try {
    doc = client.getWorkloadCertificate();
} catch (SpiffeConnectionException e) {
    if (e.getMessage().contains("empty private key")) {
        doc = retryWithBackoff(client::getWorkloadCertificate);
    } else throw e;
}

Prevention

When it happens

Trigger: getWorkloadCertificate when the selected X509SVID's getX509SvidKey() ByteString is empty.

Common situations: Incompatible or buggy SPIRE agent build omitting the key; partially overwritten protobuf message; custom Workload API stub or mock returning incomplete SVIDs.

Related errors


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