slackhq/nebula · error
error while reading ca-key: %s
Error message
error while reading ca-key: %s
What it means
signCert reads the CA private key via readInput("ca-key", *sf.caKeyPath, &claims) and wraps any read failure with this message. It means the CA key file (or stdin payload) could not be loaded at all — before any decryption is attempted — so signing cannot proceed.
Source
Thrown at cmd/nebula-cert/sign.go:139
); err != nil {
return err
}
if err := reserveOutputs(&claims,
"out-key", *sf.outKeyPath,
"out-crt", *sf.outCertPath,
"out-qr", *sf.outQRPath,
); err != nil {
return err
}
var curve cert.Curve
var caKey []byte
if !isP11 {
var rawCAKey []byte
rawCAKey, err = readInput("ca-key", *sf.caKeyPath, &claims)
if err != nil {
return fmt.Errorf("error while reading ca-key: %s", err)
}
// naively attempt to decode the private key as though it is not encrypted
caKey, _, curve, err = cert.UnmarshalSigningPrivateKeyFromPEM(rawCAKey)
if errors.Is(err, cert.ErrPrivateKeyEncrypted) {
var passphrase []byte
passphrase = []byte(os.Getenv("NEBULA_CA_PASSPHRASE"))
if len(passphrase) == 0 {
// ask for a passphrase until we get one
for i := 0; i < 5; i++ {
errOut.Write([]byte("Enter passphrase: "))
passphrase, err = pr.ReadPassword()
if errors.Is(err, ErrNoTerminal) {
return fmt.Errorf("ca-key is encrypted and must be decrypted interactively")
} else if err != nil {
return fmt.Errorf("error reading password: %s", err)
}View on GitHub (pinned to dd8f660c0a)
Solutions
- Check the file exists at the -ca-key path (ls -l)
- Fix read permissions on the CA key (chmod/chown or run as the owning user)
- Supply the key on stdin when using stdio mode
- Point -ca-key at the correct original CA key rather than a public/derived file
Example fix
// before nebula-cert sign -ca-key ./ca.key ... # file actually at ./pki/ca.key // after nebula-cert sign -ca-key ./pki/ca.key ...
Defensive patterns
Strategy: validation
Validate before calling
st, err := os.Stat(*sf.caKeyPath)
if err != nil { return fmt.Errorf("ca-key missing: %w", err) }
if st.IsDir() || st.Size() == 0 { return fmt.Errorf("ca-key %q is empty", *sf.caKeyPath) }
if f, err := os.Open(*sf.caKeyPath); err == nil { f.Close() } Try / catch
if err := signCert(args, out, errOut, StdinPasswordReader{}); err != nil {
if strings.HasPrefix(err.Error(), "error while reading ca-key") {
log.Fatalf("check -ca-key %q exists and is readable: %v", *sf.caKeyPath, err)
}
} Prevention
- Verify the -ca-key path exists before invoking sign
- Keep CA key permissions consistent (owned by the signing user)
- In CI/stdio mode, always pipe the key into stdin
- Back up the original CA key path used at creation
When it happens
Trigger: `nebula-cert sign -ca-key /path/ca.key ...` where the ca-key file is missing, unreadable (permissions), empty, or in stdio mode the key was not provided on stdin
Common situations: wrong -ca-key path; key file lost or not copied to the signing host; permissions changed after provisioning; running in CI without piping the key into stdin
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- unable to read cert; %s
- error while writing out-pub: %s
- error while writing out-qr: %s
- ca-key is encrypted and must be decrypted interactively
- error reading password: %s
AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03).
Data as JSON: /api/errors/9a501943d6211e7b.
Report an issue: GitHub.