docker/cli · error
cannot attach stdin to a TTY-enabled container because…
Error message
cannot attach stdin to a TTY-enabled container because stdin is not a terminal
What it means
Returned by In.CheckTty when a container is launched with TTY mode (-t) and stdin attached (-i), but the client process's stdin is not a real terminal (e.g. piped or redirected). Raw-mode terminal setup requires an actual TTY, so Docker refuses to start to avoid silent garbled I/O.
Solutions
- Drop the -t (tty) flag when stdin is piped: 'echo data | docker run -i ...'.
- If a TTY is genuinely required, run the command from an actual interactive shell or allocate a PTY wrapper (e.g. script, python pty).
- Separate concerns: use 'docker run -i' for piped input and reserve '-it' for human-interactive sessions.
Example fix
# before: echo hello | docker run -it alpine # after: echo hello | docker run -i alpine
Defensive patterns
Strategy: validation
Validate before calling
// Check whether stdin is a terminal before requesting -it with piped input
func shouldUseTTY(attachStdin bool, in *streams.In) bool {
if !attachStdin { return false }
return in.IsTerminal()
}
// Usage: only add "-t" when shouldUseTTY(true, dockerCLI.In()) is true. Prevention
- Use -i (not -it) when stdin is piped or redirected.
- In Go code, call In.CheckTty(attachStdin, ttyMode) early and handle the error explicitly.
- Reserve -it for genuinely interactive sessions in a real terminal.
When it happens
Trigger: Running 'echo data | docker run -it ...', 'docker run -it ... < file', or embedding docker in a CI/cron job where stdin is a pipe — i.e. attachStdin and ttyMode are both true but i.cs.isTerminal() is false.
Common situations: Piping input into an interactive container in CI pipelines; wrapping docker run in a script that redirects stdin; forgetting that -it implies an interactive TTY the host cannot provide.
Related errors
- error reading from STDIN: data is empty
- valid streams are STDIN, STDOUT and STDERR
- error: cannot perform an interactive login from a non-TTY…
- error reading from STDIN: data is empty
- tty service logs only supported with --raw
AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07).
Data as JSON: /api/errors/0256d7971bab46a6.
Report an issue: GitHub.
Appendix: source
Thrown at cli/streams/in.go:74
// value.
func (i *In) SetRawTerminal() error {
return i.cs.setRawTerminal(term.SetRawTerminal)
}
// RestoreTerminal restores the terminal state if SetRawTerminal succeeded earlier.
func (i *In) RestoreTerminal() {
i.cs.restoreTerminal()
}
// CheckTty reports an error when stdin is requested for a TTY-enabled
// container, but the client stdin is not itself a terminal (for example,
// when input is piped or redirected).
func (i *In) CheckTty(attachStdin, ttyMode bool) error {
// TODO(thaJeztah): consider inlining this code and deprecating the method.
if !ttyMode || !attachStdin || i.cs.isTerminal() {
return nil
}
return errors.New("cannot attach stdin to a TTY-enabled container because stdin is not a terminal")
}
// SetIsTerminal overrides whether a terminal is connected. It is used to
// override this property in unit-tests, and should not be depended on for
// other purposes.
func (i *In) SetIsTerminal(isTerminal bool) {
i.cs.setIsTerminal(isTerminal)
}
View on GitHub (pinned to 4f84911bfe)