amir20/dozzle · error

failed to read password

Error message

failed to read password: %w

What it means

`readPassword` uses `term.ReadPassword` when stdin is a terminal. If the terminal read syscall fails, the error is wrapped as 'failed to read password'. This guards the interactive prompt path of `dozzle generate`.

Solutions

  1. Re-run in a normal interactive terminal with a working TTY
  2. If non-interactive, pipe the password via stdin instead: `echo 'pass' | dozzle generate`
  3. Check terminal emulator / ssh session health and retry

Example fix

// before
ssh host 'dozzle generate'  # no TTY
// after
ssh -t host 'dozzle generate'
Defensive patterns

Strategy: fallback

Validate before calling

[ -t 0 ] && echo 'interactive: ensure TTY works' || echo 'piped: provide password on stdin'

Try / catch

out=$(echo "$PASSWORD" | dozzle generate 2>&1) || {
  echo "generate failed: $out" >&2
  exit 1
}

Prevention

When it happens

Trigger: Running `dozzle generate` in an environment where stdin is a terminal but the read fails: stdin closed or not readable (fd reopened/invalid), terminal I/O errors, or fd 0 replaced by a non-readable device.

Common situations: Running inside wrappers/IDE terminals with broken TTY handling; containers with a TTY allocated but stdin detached; sandboxed environments restricting terminal ioctls.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


AI-assisted analysis of amir20/dozzle@d9463cbe21 (2026-09-07). Data as JSON: /api/errors/6d65bae4a061932c. Report an issue: GitHub.

Appendix: source

Thrown at internal/support/cli/generate_command.go:71

	if _, err := os.Stdout.Write(buffer.Bytes()); err != nil {
		return fmt.Errorf("failed to write to stdout: %w", err)
	}

	return nil
}

// readPassword reads a password from stdin. Prompts are written to stderr so
// they don't pollute stdout (which is commonly redirected to users.yml). When
// stdin is a terminal the input is read without echo; otherwise a single line
// is read (supports piping, e.g. `echo secret | dozzle generate ...`).
func readPassword() (string, error) {
	fd := int(os.Stdin.Fd())
	if term.IsTerminal(fd) {
		fmt.Fprint(os.Stderr, "Password: ")
		bytePassword, err := term.ReadPassword(fd)
		fmt.Fprintln(os.Stderr)
		if err != nil {
			return "", fmt.Errorf("failed to read password: %w", err)
		}
		return strings.TrimRight(string(bytePassword), "\r\n"), nil
	}

	reader := bufio.NewReader(os.Stdin)
	line, err := reader.ReadString('\n')
	if err != nil && line == "" {
		return "", fmt.Errorf("failed to read password from stdin: %w", err)
	}
	return strings.TrimRight(line, "\r\n"), nil
}

View on GitHub (pinned to d9463cbe21)