t8y2/dbx · error
JKS private key entry has no certificate chain
Error message
JKS private key entry has no certificate chain
What it means
loadClientKeyStore extracts a client certificate chain from a JKS keystore for mutual TLS. After appending each chain certificate, if none were collected, it returns this error: the PrivateKeyEntry exists but carries no certificate chain, so a tls.Certificate cannot be constructed.
Source
Thrown at agents/drivers/argo-go/zookeeper_tls.go:165
continue
}
entry, getErr := store.GetPrivateKeyEntry(alias, passwordBytes)
if getErr != nil {
return tls.Certificate{}, getErr
}
privateKey, parseErr := parsePrivateKey(entry.PrivateKey)
if parseErr != nil {
return tls.Certificate{}, parseErr
}
result := tls.Certificate{PrivateKey: privateKey}
for index, certificate := range entry.CertificateChain {
result.Certificate = append(result.Certificate, certificate.Content)
if index == 0 {
result.Leaf, _ = x509.ParseCertificate(certificate.Content)
}
}
if len(result.Certificate) == 0 {
return tls.Certificate{}, errors.New("JKS private key entry has no certificate chain")
}
return result, nil
}
return tls.Certificate{}, errors.New("JKS keystore contains no private key entry")
default:
return tls.Certificate{}, fmt.Errorf("unsupported store type %q", storeType)
}
}
func normalizedStoreType(storeType, path string) string {
value := strings.ToUpper(strings.TrimSpace(storeType))
switch value {
case "P12", "PFX", "PKCS#12":
return "PKCS12"
case "X509", "X.509":
return "PEM"
case "":
switch strings.ToLower(filepath.Ext(path)) {View on GitHub (pinned to c0390bff16)
Solutions
- Regenerate/repair the entry so the chain is stored: keytool -genkeypair then -importcert the full chain, or use -importkeystore from a PKCS12 that includes the chain
- Verify with keytool -list -v -keystore keystore.jks that the entry is PrivateKeyEntry with a chain length >= 1
- If only a key without certs is needed, switch to a PEM keystore with cert+key files
- Check the store password so the private key entry is fully decrypted
Example fix
// before: key without chain # keytool -genkeypair -alias client -keystore client.jks -dname cn=client // after: include full chain # keytool -certreq ... && keytool -importcert -file chain.p7b -keystore client.jks -alias client
Defensive patterns
Strategy: validation
Validate before calling
out, _ := exec.Command("keytool", "-list", "-v", "-keystore", keystorePath,
"-storepass", password).Output()
if !strings.Contains(string(out), "PrivateKeyEntry") ||
!strings.Contains(string(out), "Certificate chain length:") {
return fmt.Errorf("keystore %s lacks a private key with chain", keystorePath)
} Try / catch
cert, err := buildTLSConfig(...)
if errors.Is(err, errNoCertChain) { /* regenerate keystore */ } Prevention
- Generate client keystores from PKCS12 bundles that include key + full chain
- Run keytool -list -v as a pre-flight check in deployment scripts
- Do not reuse truststores as client keystores
When it happens
Trigger: Building the ZooKeeper TLS config with a keystore whose private key entry has an empty certificate chain, e.g. keytool entries imported without a -chain or generated keypairs whose certs were deleted.
Common situations: Keystore created with 'keytool -genkeypair' in a environment where the self-signed chain was truncated; a JKS holding only trusted (TrustedCertEntry) certificates but no PrivateKeyEntry chain; corrupted keystore after migration between JDK versions.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- JKS keystore contains no private key entry
- JKS private key entry has no certificate chain
- JKS keystore contains no private key entry
- load ZooKeeper keystore: %w
- Client certificate and key must be provided together
AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05).
Data as JSON: /api/errors/218e06c1a505c2e2.
Report an issue: GitHub.