{"record":{"id":"a4bd43dd05eeb159","repo":"slackhq/nebula","slug":"error-while-unmarshaling-pki-key-s-s","errorCode":null,"errorMessage":"error while unmarshaling pki.key %s: %s","messagePattern":"error while unmarshaling pki\\.key (.+?): (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pki.go","lineNumber":500,"sourceCode":"\t\tif network.Addr().Is4() {\n\t\t\taddr := network.Masked().Addr().As4()\n\t\t\tmask := net.CIDRMask(network.Bits(), network.Addr().BitLen())\n\t\t\tbinary.BigEndian.PutUint32(addr[:], binary.BigEndian.Uint32(addr[:])|^binary.BigEndian.Uint32(mask))\n\t\t\tcs.myVpnBroadcastAddrsTable.Insert(netip.PrefixFrom(netip.AddrFrom4(addr), network.Addr().BitLen()))\n\t\t}\n\t}\n\n\treturn &cs, nil\n}\n\nfunc loadPrivateKey(privPathOrPEM string) (rawKey []byte, curve cert.Curve, isPkcs11 bool, err error) {\n\tvar pemPrivateKey []byte\n\tif strings.Contains(privPathOrPEM, \"-----BEGIN\") {\n\t\tpemPrivateKey = []byte(privPathOrPEM)\n\t\tprivPathOrPEM = \"<inline>\"\n\t\trawKey, _, curve, err = cert.UnmarshalPrivateKeyFromPEM(pemPrivateKey)\n\t\tif err != nil {\n\t\t\treturn nil, curve, false, fmt.Errorf(\"error while unmarshaling pki.key %s: %s\", privPathOrPEM, err)\n\t\t}\n\t} else if strings.HasPrefix(privPathOrPEM, \"pkcs11:\") {\n\t\trawKey = []byte(privPathOrPEM)\n\t\treturn rawKey, cert.Curve_P256, true, nil\n\t} else {\n\t\tpemPrivateKey, err = os.ReadFile(privPathOrPEM)\n\t\tif err != nil {\n\t\t\treturn nil, curve, false, fmt.Errorf(\"unable to read pki.key file %s: %s\", privPathOrPEM, err)\n\t\t}\n\t\trawKey, _, curve, err = cert.UnmarshalPrivateKeyFromPEM(pemPrivateKey)\n\t\tif err != nil {\n\t\t\treturn nil, curve, false, fmt.Errorf(\"error while unmarshaling pki.key %s: %s\", privPathOrPEM, err)\n\t\t}\n\t}\n\n\treturn\n}\n","sourceCodeStart":482,"sourceCodeEnd":518,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/pki.go#L482-L518","documentation":"loadPrivateKey treats pki.key values not starting with '-----BEGIN' or 'pkcs11:' as file paths and calls os.ReadFile; the file could not be read. The %s fields carry the path and the OS error (e.g. no such file, permission denied).","triggerScenarios":"loadPrivateKey (from newCertStateFromConfig): pki.key is a path and os.ReadFile fails — file missing, wrong path, unreadable permissions, or directory instead of file.","commonSituations":"Deployed config references a key path that wasn't mounted; systemd service lacks read permission on the key; typo in path; container secret not mounted.","solutions":["Fix the pki.key path or create/copy the key file there","Fix permissions so the nebula process user can read the file (chmod 600, correct owner)","If the key is inline PEM, ensure it starts with '-----BEGIN' so it isn't treated as a path"],"exampleFix":"// before\npki:\n  key: /etc/nebula/pki.key   # file absent\n// after\nnebula-cert keygen -out-key /etc/nebula/pki.key\nchown nebula:nebula /etc/nebula/pki.key && chmod 600 /etc/nebula/pki.key","handlingStrategy":"validation","validationCode":"// validate inline or file-based key before handing it to nebula\nfunc validatePrivateKey(keyValue string) error {\n    if strings.Contains(keyValue, \"-----BEGIN\") {\n        _, _, _, err := cert.UnmarshalPrivateKeyFromPEM([]byte(keyValue))\n        return err\n    }\n    if strings.HasPrefix(keyValue, \"pkcs11:\") { return nil }\n    b, err := os.ReadFile(keyValue)\n    if err != nil { return err }\n    _, _, _, err = cert.UnmarshalPrivateKeyFromPEM(b)\n    return err\n}","typeGuard":"func isInlinePEMKey(v string) bool { return strings.Contains(v, \"-----BEGIN\") }\nfunc isPkcs11URI(v string) bool { return strings.HasPrefix(v, \"pkcs11:\") }","tryCatchPattern":"if err := loadPrivateKey(key); err != nil {\n    if strings.Contains(err.Error(), \"error while unmarshaling pki.key\") {\n        log.Fatalf(\"pki.key is not a valid unencrypted nebula private key PEM: %v\", err)\n    }\n    return err\n}","preventionTips":["Prefer file paths over inline PEM to avoid newline/quoting corruption","Never use encrypted private keys; strip passphrases first","Test key parsing in a pre-start validation step"],"tags":["pki","filesystem","config"],"backgroundTag":"file-not-found","analyzedSha":"dd8f660c0ac37903ec4080ca4d3c861ba9342ceb","analyzedAt":"2026-09-03T11:13:55.444Z","contentChangedAt":"2026-09-03T11:13:55.444Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}