gastownhall/beads · error
failed to read confirmation: %w
Error message
failed to read confirmation: %w
What it means
When the user chooses option [2] (reinitialize database), `RepoFingerprint` asks for a final confirmation before deleting the database file, reading the reply with `repoFingerprintReadLine()`. If that second stdin read fails, the destructive path is aborted and the underlying error is wrapped as `failed to read confirmation: %w`. Because the confirmation guards a DELETE, the error path deliberately performs no changes.
Source
Thrown at cmd/bd/doctor/fix/repo_fingerprint.go:148
switch response {
case "1":
return updateRepoIDInProcess(path, beadsDir, false)
case "2":
// Detect backend to determine what to remove
cfg, cfgErr := configfile.Load(beadsDir)
if cfgErr != nil || cfg == nil {
cfg = configfile.DefaultConfig()
}
dbPath := cfg.DatabasePath(beadsDir)
isDolt := cfg.GetBackend() == configfile.BackendDolt
// Confirm before destructive action
fmt.Printf(" ⚠️ This will DELETE %s. Continue? [y/N]: ", dbPath)
confirm, err := repoFingerprintReadLine()
if err != nil {
return fmt.Errorf("failed to read confirmation: %w", err)
}
confirm = strings.TrimSpace(strings.ToLower(confirm))
if confirm != "y" && confirm != "yes" {
fmt.Println(" → Skipped (canceled)")
return nil
}
// Remove database and reinitialize in-process
fmt.Printf(" → Removing %s...\n", dbPath)
if isDolt {
if err := os.RemoveAll(dbPath); err != nil && !os.IsNotExist(err) {
return fmt.Errorf("failed to remove Dolt database: %w", err)
}
} else {
if err := os.Remove(dbPath); err != nil && !os.IsNotExist(err) {
return fmt.Errorf("failed to remove database: %w", err)
}
_ = os.Remove(dbPath + "-wal")View on GitHub (pinned to 71377f2769)
Solutions
- Supply answers for BOTH prompts, e.g. `printf '2\ny\n' | bd ...` (or 'n' to cancel safely).
- Use `--yes` mode instead, which skips all prompts and takes the safe non-destructive path.
- Run interactively in a real terminal so both reads succeed.
- If the underlying error indicates a broken TTY, fix the terminal/SSH session and retry.
Example fix
// before: pipe closes after first answer, confirmation read hits EOF echo "2" | bd doctor --fix // after: answer both prompts, or use auto-yes mode printf '2\ny\n' | bd doctor --fix # or: bd doctor --fix --yes
Defensive patterns
Strategy: try-catch
Validate before calling
func canPrompt() error {
fi, err := os.Stdin.Stat()
if err != nil {
return err
}
if (fi.Mode() & os.ModeCharDevice) == 0 && fi.Size() == 0 {
return errors.New("stdin is empty or not interactive; use --yes")
}
return nil
}
// call only if canPrompt() == nil, else pass autoYes=true Type guard
if errors.Is(err, io.EOF) || errors.Is(err, os.ErrClosed) {
// stdin unusable: fall back to non-interactive mode
} Try / catch
if err := fix.RepoFingerprint(path, false); err != nil {
if errors.Is(err, io.EOF) || errors.Is(err, os.ErrClosed) {
err = fix.RepoFingerprint(path, true) // retry non-interactively
}
if err != nil {
log.Fatal(err)
}
} Prevention
- Prefer autoYes=true (or --yes) in scripts, CI, and daemons — never rely on stdin availability.
- Check stdin is a character device before invoking interactive commands.
- When feeding answers via pipes, supply every prompt's answer plus newline in order.
- Unwrap the returned error (`errors.Is/As`) to distinguish EOF vs closed vs TTY errors.
When it happens
Trigger: User answered '2' at the choice prompt, then the confirmation read fails: stdin hit EOF (input pipe exhausted after the first answer), non-interactive environment (CI, /dev/null stdin), or terminal I/O error between the two prompts.
Common situations: Scripting the interactive flow with `echo 2 | bd ...` — the pipe delivers '2' but is at EOF for the confirmation read; automated harnesses that answer only the first prompt; dropping the terminal connection after the first answer.
Related errors
- failed to read file: %w
- %s
- line %d (%s): %w
- line %d: %w
- %w. Hint: run 'bd init' to create a database in the current
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/4a0f46ca4b8aa2e3.
Report an issue: GitHub.