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

  1. Ensure stdin is open and readable when the passphrase prompt appears
  2. Run inside a working interactive terminal and type the passphrase at the prompt
  3. Check any custom PasswordReader wiring for bugs in its ReadPassword implementation
  4. 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

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


AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03). Data as JSON: /api/errors/49d8bc4213476944. Report an issue: GitHub.