gravitational/teleport · error
chain not allowed with an empty certificate
Error message
chain not allowed with an empty certificate
What it means
In lib/subca/parsed.go, validateCertificateOverride parses the optional certificate and chain fields of a CA override. If a chain is supplied but no override certificate is set, there is no leaf/issuer anchor to attach the chain to, so the function rejects the combination with this error. The library requires the override certificate itself to be provided whenever an intermediate chain accompanies it.
Source
Thrown at lib/subca/parsed.go:268
}
}
// Validate "required" fields now that we know both Certificate and PublicKey
// are valid.
switch {
case co.GetDisabled() && co.GetPublicKey() == "" && co.GetCertificate() == "":
return nil, "", errors.New("certificate or public key required")
case co.GetDisabled():
// OK, determined above to have either PublicKey or Certificate.
case co.GetCertificate() == "":
return nil, "", errors.New("certificate required")
}
// Chain.
var chain []*x509.Certificate
if len(co.GetChain()) > 0 {
if cert == nil {
return nil, "", errors.New("chain not allowed with an empty certificate")
}
// The exact number is arbitrary, the fact that a cap exists isn't.
const maxChainLength = 10
if len(co.GetChain()) > maxChainLength {
return nil, "chain", fmt.Errorf(
"certificate chain has too many entries (%d > %d)", len(co.GetChain()), maxChainLength)
}
chain = make([]*x509.Certificate, len(co.GetChain()))
prev := cert
for i, chainPEM := range co.GetChain() {
chainCert, err := ParseCertificateOverrideCertificate(chainPEM)
if err != nil {
return nil, fmt.Sprintf("chain[%d]", i), err
}
chainSub := chainCert.Subject.String()
View on GitHub (pinned to 1283425b60)
Solutions
- Set the override certificate (co.Cert) to the issuing CA certificate that the chain extends.
- If the first certificate in your PEM is actually the override certificate, move it from 'chain' into the certificate field.
- If no chain is needed, remove the chain entries entirely instead of leaving them with an empty cert.
Example fix
// before
spec:
cert: ""
chain:
- |
-----BEGIN CERTIFICATE-----
...(intermediate)...
// after
spec:
cert: |
-----BEGIN CERTIFICATE-----
...(override CA)...
chain:
- |
-----BEGIN CERTIFICATE-----
...(intermediate)... Defensive patterns
Strategy: validation
Validate before calling
if len(override.Chain) > 0 && override.Cert == "" {
return fmt.Errorf("invalid config: chain requires a certificate")
} Prevention
- Validate CA override manifests (cert present iff needed, chain under 10 entries) before applying them.
- Script PEM splitting so the first certificate goes to 'cert', the rest to 'chain'.
- Never leave 'chain' populated with an empty 'cert' field in templates.
When it happens
Trigger: Calling ValidateAndParseCAOverride with a CAOverride spec whose 'chain' field is non-empty while 'cert' is empty or nil. Typically a YAML/manifest that defines chain entries (intermediates) but omits the main override certificate.
Common situations: Operators pasting a full PEM bundle into 'chain' but forgetting the leaf CA in 'cert'; templates that split a PEM into the wrong fields; automation that strips the first certificate into a separate variable and ends up with an empty cert.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- override certificate should not be included in chain
- not a CA certificate (IsCA=false)
- basic constraints not valid (BasicConstraintsValid=false)
- missing KeyUsage keyCertSign
- NotBefore > NotAfter
AI-assisted analysis of gravitational/teleport@1283425b60 (2026-09-02).
Data as JSON: /api/errors/ad3f3a448b26182c.
Report an issue: GitHub.