slackhq/nebula · error
v1 certificate already found in pki.cert
Error message
v1 certificate already found in pki.cert
What it means
pki.cert may contain a chain of certificates, but at most one v1 certificate and one v2 certificate are allowed. If a second cert.Version1 certificate is encountered during parsing, this error is returned to reject the malformed file.
Source
Thrown at pki.go:347
}
}
var crt, v1, v2 cert.Certificate
for {
// Load the certificate
crt, rawCert, err = loadCertificate(rawCert)
if err != nil {
return nil, err
}
if fips140.Enforced() && crt.Curve() != cert.Curve_P256 {
return nil, fmt.Errorf("pki: use of %s is not allowed in FIPS 140-only mode", crt.Curve())
}
switch crt.Version() {
case cert.Version1:
if v1 != nil {
return nil, fmt.Errorf("v1 certificate already found in pki.cert")
}
v1 = crt
case cert.Version2:
if v2 != nil {
return nil, fmt.Errorf("v2 certificate already found in pki.cert")
}
v2 = crt
default:
return nil, fmt.Errorf("unknown certificate version %v", crt.Version())
}
if len(rawCert) == 0 || strings.TrimSpace(string(rawCert)) == "" {
break
}
}
if v1 == nil && v2 == nil {
return nil, errors.New("no certificates found in pki.cert")View on GitHub (pinned to dd8f660c0a)
Solutions
- Edit pki.cert to keep exactly one v1 certificate (plus at most one v2) and remove the duplicate.
- Regenerate pki.cert cleanly from the single intended certificate file.
- Fix any `cat old.cert >> pki.cert` rotation scripts to use atomic replace instead of append.
- Verify afterwards with openssl/nebula-cert tooling that the file parses as a single chain.
Example fix
# before (rotating) cat new.cert >> /etc/nebula/pki.cert # after (rotating) install -m 0644 new.cert /etc/nebula/pki.cert
Defensive patterns
Strategy: validation
Validate before calling
// Before reload: count v1/v2 PEM blocks in pki.cert
func checkSingleCerts(raw []byte) error {
rest := raw; v1, v2 := 0, 0
for len(rest) > 0 {
var crt *x509.Certificate
crt, rest, _ = parseOne(rest)
switch crt.Version {
case 1: v1++
case 2: v2++
}
if v1 > 1 { return errors.New("pki.cert contains multiple v1 certificates") }
if v2 > 1 { return errors.New("pki.cert contains multiple v2 certificates") }
}
return nil
} Try / catch
cs, err := newCertStateFromConfig(...)
if err != nil {
if strings.Contains(err.Error(), "already found in pki.cert") {
return fmt.Errorf("pki.cert has duplicate certs; rebuild it as a single chain: %w", err)
}
return err
} Prevention
- Replace pki.cert atomically on rotation (install/mv), never append with >>.
- Build pki.cert from a single source of truth in automation (one template, one cert).
- After any cert change, parse the file and assert <=1 v1 and <=1 v2 before reload.
- Review shell scripts that touch pki.cert for redirection mistakes.
When it happens
Trigger: reloadCerts -> newCertStateFromConfig when pki.cert contains two or more v1-format certificates, typically from concatenating two complete cert files or appending a renewed cert of the same version instead of replacing it.
Common situations: Operators concatenating old and new certs during rotation; shell redirection with `>>` instead of `>` overwriting pki.cert; packaging scripts bundling multiple intermediates of the same version; copy-paste mishaps joining two PEM blobs.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- v2 certificate already found in pki.cert
- error while unmarshaling pki.cert: %w
- no networks encoded in certificate
- host certificate is a CA certificate
- error while adding CA certificate to CA trust store: %s
AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03).
Data as JSON: /api/errors/bcf6961437fe5b42.
Report an issue: GitHub.