slackhq/nebula · error
unable to read pki.key file %s: %s
Error message
unable to read pki.key file %s: %s
What it means
Wrapping error in loadPrivateKey: the inline PEM supplied via pki.key (a literal PEM string containing -----BEGIN rather than a path) failed to unmarshal as a private key. The offending value is reported as "<inline>" with the underlying error appended via %s.
Source
Thrown at pki.go:508
return &cs, nil
}
func loadPrivateKey(privPathOrPEM string) (rawKey []byte, curve cert.Curve, isPkcs11 bool, err error) {
var pemPrivateKey []byte
if strings.Contains(privPathOrPEM, "-----BEGIN") {
pemPrivateKey = []byte(privPathOrPEM)
privPathOrPEM = "<inline>"
rawKey, _, curve, err = cert.UnmarshalPrivateKeyFromPEM(pemPrivateKey)
if err != nil {
return nil, curve, false, fmt.Errorf("error while unmarshaling pki.key %s: %s", privPathOrPEM, err)
}
} else if strings.HasPrefix(privPathOrPEM, "pkcs11:") {
rawKey = []byte(privPathOrPEM)
return rawKey, cert.Curve_P256, true, nil
} else {
pemPrivateKey, err = os.ReadFile(privPathOrPEM)
if err != nil {
return nil, curve, false, fmt.Errorf("unable to read pki.key file %s: %s", privPathOrPEM, err)
}
rawKey, _, curve, err = cert.UnmarshalPrivateKeyFromPEM(pemPrivateKey)
if err != nil {
return nil, curve, false, fmt.Errorf("error while unmarshaling pki.key %s: %s", privPathOrPEM, err)
}
}
return
}
func loadCertificate(b []byte) (cert.Certificate, []byte, error) {
c, b, err := cert.UnmarshalCertificateFromPEM(b)
if err != nil {
return nil, b, fmt.Errorf("error while unmarshaling pki.cert: %w", err)
}
if c.Expired(time.Now()) {
return nil, b, fmt.Errorf("nebula certificate for this host is expired")View on GitHub (pinned to dd8f660c0a)
Solutions
- Fix the inline PEM to be a valid Nebula private key (correct banner, untruncated base64)
- Point pki.key at the key file path instead of pasting the PEM
- If the key is encrypted, provide it in a form/config the loader supports
Defensive patterns
Strategy: validation
Validate before calling
// stat the key file and check readability before starting
func keyFileReadable(path string) error {
fi, err := os.Stat(path)
if err != nil { return err }
if fi.IsDir() { return fmt.Errorf("%s is a directory", path) }
f, err := os.Open(path); if err != nil { return err }
return f.Close()
} Try / catch
if err := loadPrivateKey(keyPath); err != nil {
var pathErr *os.PathError
if errors.As(err, errors.Unwrap(err), &pathErr) || strings.Contains(err.Error(), "unable to read pki.key") {
log.Fatalf("cannot read pki.key at %s; check path, mount and permissions: %v", keyPath, err)
}
return err
} Prevention
- Mount/copy the key file before the nebula unit starts (systemd After=/Requires=)
- Set owner to the nebula service user and mode 600
- Use absolute paths and verify them in deployment manifests
When it happens
Trigger: Thrown at pki.go:508 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03).
Data as JSON: /api/errors/15d1d702f2f131e5.
Report an issue: GitHub.