docker/cli · error
cowardly refusing to save to a terminal. Use the -o flag or…
Error message
cowardly refusing to save to a terminal. Use the -o flag or redirect
What it means
runSave() streams a binary tar archive of image layers to stdout by default. If no -o file is given and stdout is a TTY (dockerCLI.Out().IsTerminal()), it refuses to avoid dumping binary onto the terminal. The guard mirrors the export-to-terminal protection.
Solutions
- Use -o to write a file: `docker save -o out.tar myimage`
- Redirect stdout: `docker save myimage > out.tar`
- Pipe to a consumer so stdout is not a TTY: `docker save myimage | gzip > out.tar.gz`
Example fix
// before docker save myimage // after docker save -o out.tar myimage // or docker save myimage > out.tar
Defensive patterns
Strategy: validation
Validate before calling
if opts.output == "" && dockerCLI.Out().IsTerminal() {
return errors.New("refusing to save to terminal; pass -o <file> or redirect stdout")
} Prevention
- Always pass -o <file> when saving images
- Redirect stdout to a file in scripts: `docker save img > out.tar`
- Detect TTY in wrapper scripts (`[ -t 1 ]`) before streaming binary
When it happens
Trigger: Running `docker save myimage` in an interactive shell with no -o flag and no stdout redirection.
Common situations: Forgetting -o; intending to pipe but running interactively; expecting a file to be written automatically.
Related errors
- cowardly refusing to export to a terminal, specify a file…
- requested load from stdin, but stdin is empty
- invalid argument: can't use stdin for both build context…
- --quiet is not yet supported with --tree
- --no-trunc is not yet supported with --tree
AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07).
Data as JSON: /api/errors/c41bd4cddd26283a.
Report an issue: GitHub.
Appendix: source
Thrown at cli/command/image/save.go:73
func runSave(ctx context.Context, dockerCLI command.Cli, opts saveOptions) error {
var options []client.ImageSaveOption
platformList := []ocispec.Platform{}
for _, p := range opts.platform {
pp, err := platforms.Parse(p)
if err != nil {
return fmt.Errorf("invalid platform: %w", err)
}
platformList = append(platformList, pp)
}
if len(platformList) > 0 {
options = append(options, client.ImageSaveWithPlatforms(platformList...))
}
var output io.Writer
if opts.output == "" {
if dockerCLI.Out().IsTerminal() {
return errors.New("cowardly refusing to save to a terminal. Use the -o flag or redirect")
}
output = dockerCLI.Out()
} else {
writer, err := atomicwriter.New(opts.output, 0o600)
if err != nil {
return fmt.Errorf("failed to save image: %w", err)
}
defer writer.Close()
output = writer
}
responseBody, err := dockerCLI.Client().ImageSave(ctx, opts.images, options...)
if err != nil {
return err
}
defer responseBody.Close()
_, err = io.Copy(output, responseBody)View on GitHub (pinned to 4f84911bfe)