{"record":{"id":"024b7d80dcdc4de6","repo":"restic/restic","slug":"readpassword-w","errorCode":null,"errorMessage":"ReadPassword: %w","messagePattern":"ReadPassword: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/terminal/password.go","lineNumber":50,"sourceCode":"\t\tif err != nil {\n\t\t\treturn\n\t\t}\n\t\t_, err = fmt.Fprintln(out)\n\t}()\n\n\tselect {\n\tcase <-ctx.Done():\n\t\terr := term.Restore(inFd, state)\n\t\tif err != nil {\n\t\t\t_, _ = fmt.Fprintf(out, \"unable to restore terminal state: %v\\n\", err)\n\t\t}\n\t\treturn \"\", ctx.Err()\n\tcase <-done:\n\t\t// clean shutdown, nothing to do\n\t}\n\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"ReadPassword: %w\", err)\n\t}\n\n\treturn string(buf), nil\n}\n","sourceCodeStart":32,"sourceCodeEnd":55,"githubUrl":"https://github.com/restic/restic/blob/a80be1478a4c537f8396e0db2b05120aa78f11e0/internal/terminal/password.go#L32-L55","documentation":"The interactive password prompt called term.ReadPassword on the terminal and it failed. This is terminal-layer I/O: stdin is not a real terminal (raw-mode ioctl fails), the tty was closed, or the read was interrupted. The function has already restored terminal state and cancelled cleanly on ctx.Done; this branch is a hard read failure.","triggerScenarios":"Running restic where stdin is a pipe/file rather than a tty and no password source is configured; running under a service manager/cron with no controlling terminal; ssh session dropped mid-prompt; a closed /dev/tty.","commonSituations":"Scripts/CI calling restic interactively; Docker run without -t; cron jobs or systemd services without password configuration; double-bg session detaching the tty.","solutions":["Provide the password non-interactively: --password-file, RESTIC_PASSWORD_FILE, or RESTIC_PASSWORD","For scripted stdin use: restic backup ... < pwfile (termstatus reads a line when not a tty)","Allocate a tty when interactivity is intended: ssh -t, docker run -it","Ensure /dev/tty exists and is usable in the execution context (containers, chroots)"],"exampleFix":"# before (cron job, no tty)\nrestic backup /data\n# Error: ReadPassword: inappropriate ioctl for device\n\n# after\necho 's3cret' > /etc/restic/pw && chmod 600 /etc/restic/pw\nRESTIC_PASSWORD_FILE=/etc/restic/pw restic backup /data","handlingStrategy":"validation","validationCode":"// decide the password source up front; never rely on an interactive prompt\nif os.Getenv(\"RESTIC_PASSWORD_FILE\") == \"\" && os.Getenv(\"RESTIC_PASSWORD\") == \"\" {\n    if !term.IsTerminal(int(os.Stdin.Fd())) {\n        return errors.New(\"no tty and no password configured; set RESTIC_PASSWORD_FILE\")\n    }\n}","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"ReadPassword:\") {\n    // switch strategy: read from --password-file / env var instead of tty\n}","preventionTips":["Always set RESTIC_PASSWORD_FILE in scripts, cron, containers","Use ssh -t / docker -it when interactive prompting is intended","Smoke-test automation with an empty environment to catch tty assumptions"],"tags":["go","restic","terminal","password","io"],"backgroundTag":null,"analyzedSha":"a80be1478a4c537f8396e0db2b05120aa78f11e0","analyzedAt":"2026-08-15T15:30:29.928Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}