slackhq/nebula · error
error reading password: %s
Error message
error reading password: %s
What it means
During the encrypted-CA-key passphrase loop, if pr.ReadPassword() fails for any reason other than ErrNoTerminal, signCert wraps it as "error reading password". This is an error obtaining the passphrase from the password reader (StdinPasswordReader or a test-injected reader), distinct from a wrong passphrase.
Source
Thrown at cmd/nebula-cert/sign.go:156
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)
}
if len(passphrase) > 0 {
break
}
}
if len(passphrase) == 0 {
return fmt.Errorf("cannot open encrypted ca-key without passphrase")
}
}
curve, caKey, _, err = cert.DecryptAndUnmarshalSigningPrivateKey(passphrase, rawCAKey)
if err != nil {
return fmt.Errorf("error while parsing encrypted ca-key: %s", err)
}
} else if err != nil {
return fmt.Errorf("error while parsing ca-key: %s", err)
}
}View on GitHub (pinned to dd8f660c0a)
Solutions
- Ensure stdin is open and readable when the passphrase prompt appears
- Run inside a working interactive terminal and type the passphrase at the prompt
- Check any custom PasswordReader wiring for bugs in its ReadPassword implementation
- Decrypt the CA key ahead of time to avoid the prompt path entirely
Example fix
// before nebula-cert sign -ca-key enc.key < /dev/null # stdin closed: ReadPassword errors // after nebula-cert sign -ca-key enc.key # interactive stdin available
Defensive patterns
Strategy: try-catch
Validate before calling
if _, err := os.Stdin.Stat(); err != nil {
return fmt.Errorf("stdin unusable for passphrase prompt: %w", err)
}
if fi, _ := os.Stdin.Stat(); fi.Mode()&os.ModeCharDevice == 0 && !allowPrompt {
return fmt.Errorf("stdin not interactive; cannot read password")
} Try / catch
if err := signCert(args, out, errOut, StdinPasswordReader{}); err != nil {
if strings.Contains(err.Error(), "error reading password") {
log.Printf("passphrase read failed: %v; ensure stdin is open and interactive", err)
}
} Prevention
- Never run encrypted-key signing with stdin pointed at /dev/null or a closed pipe
- Test the password prompt path in the same environment used for production runs
- Audit custom PasswordReader implementations for read errors
- Prefer decrypting the CA key ahead of time to skip the prompt entirely
When it happens
Trigger: ReadPassword returns a non-ErrNoTerminal error while signCert tries to prompt up to 5 times for the encrypted CA key passphrase — e.g. stdin read failure, closed stdin mid-prompt, or a custom PasswordReader implementation returning an error
Common situations: stdin closed or redirected from a device that errors on read; broken pipe to the terminal; a scripted PasswordReader (in tests or wrappers) that fails; exotic terminals where raw-mode password reading is unsupported
Related errors
- ca-key is encrypted and must be decrypted interactively
- ErrNoTerminal
- error while reading ca-key: %s
- no cipher state available to encrypt
- no cipher state available to encrypt
AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03).
Data as JSON: /api/errors/49d8bc4213476944.
Report an issue: GitHub.