slackhq/nebula · error
unable to read pki.cert file %s: %s
Error message
unable to read pki.cert file %s: %s
What it means
newCertStateFromConfig loads the certificate chain either from an inline PEM string or by reading the pki.cert file from disk. When the path is a file (not inline PEM) and os.ReadFile fails, this error reports the path and the OS error.
Source
Thrown at pki.go:328
if err != nil {
return nil, err
}
var rawCert []byte
pubPathOrPEM := c.GetString("pki.cert", "")
if pubPathOrPEM == "" {
return nil, errors.New("no pki.cert path or PEM data provided")
}
if strings.Contains(pubPathOrPEM, "-----BEGIN") {
rawCert = []byte(pubPathOrPEM)
pubPathOrPEM = "<inline>"
} else {
rawCert, err = os.ReadFile(pubPathOrPEM)
if err != nil {
return nil, fmt.Errorf("unable to read pki.cert file %s: %s", pubPathOrPEM, err)
}
}
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 {View on GitHub (pinned to dd8f660c0a)
Solutions
- Fix the pki.cert path in config (use an absolute path) and confirm the file exists.
- Check file permissions so the nebula process user can read it.
- Verify the inline-PEM vs path distinction: an inline PEM string bypasses the file read entirely.
- If path is relative, either make it absolute or start nebula from the intended working directory.
Example fix
# before pki: cert: ./pki.cert # after pki: cert: /etc/nebula/pki.cert
Defensive patterns
Strategy: validation
Validate before calling
func checkCertReadable(path string) error {
if path == "" { return errors.New("pki.cert path empty") }
fi, err := os.Stat(path)
if err != nil { return fmt.Errorf("pki.cert %s: %w", path, err) }
if fi.IsDir() { return fmt.Errorf("pki.cert %s is a directory", path) }
f, err := os.Open(path); if err != nil { return fmt.Errorf("pki.cert %s unreadable: %w", path, err) }
f.Close(); return nil
}
// run before starting nebula Try / catch
cs, err := newCertStateFromConfig(...)
if err != nil {
var pathErr *os.PathError
if strings.Contains(err.Error(), "unable to read pki.cert file") && errors.As(err, &pathErr) {
return fmt.Errorf("fix pki.cert path/permissions: %w", err)
}
return err
} Prevention
- Always use absolute paths for pki.cert and ca.crt in the config.
- Pre-verify file existence and readability as the exact user nebula runs as (systemd User=).
- Add a startup preflight that stats cert paths before launching the service.
- Avoid inline-PEM/path ambiguity: inline PEM is detected by content, otherwise treat the value strictly as a path.
When it happens
Trigger: reloadCerts -> newCertStateFromConfig with a pki.cert path that doesn't exist, lacks read permission, is a directory, or otherwise fails os.ReadFile.
Common situations: Nebula started from a different working directory with a relative path; cert file deleted or renamed; wrong user/permissions (e.g. running as non-root without access to /etc/nebula); typo in the `cert:` path in config; systemd unit with a different WorkingDirectory.
Related errors
- v1 certificate already found in pki.cert
- v2 certificate already found in pki.cert
- error while unmarshaling pki.key %s: %s
- error while unmarshaling pki.cert: %w
- no networks encoded in certificate
AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03).
Data as JSON: /api/errors/8b9e16188c3a0279.
Report an issue: GitHub.