docker/cli · error

cowardly refusing to export to a terminal, specify a file…

Error message

cowardly refusing to export to a terminal, specify a file path

What it means

`docker context export` serializes a context into a binary tar archive. When the destination is "-" (stdout), writeTo() checks dockerCli.Out().IsTerminal() and refuses to dump raw binary bytes onto an interactive terminal, since that would corrupt the terminal display with control sequences. The guard is a safety measure, not a real I/O failure: it fires only for dest=="-" while stdout is a TTY.

Solutions

  1. Pass a real file path instead of "-": `docker context export <name> path.dockercontext`
  2. Redirect stdout to a file: `docker context export <name> - > ctx.tar`
  3. Pipe into a consuming command so stdout is not a TTY: `docker context export <name> - | tar -tv`

Example fix

// before
docker context export myctx -
// after
docker context export myctx myctx.dockercontext
// or
docker context export myctx - > myctx.tar
Defensive patterns

Strategy: validation

Validate before calling

// Validate destination before exporting to a terminal
dest := "-"
if dest == "-" && dockerCli.Out().IsTerminal() {
    return fmt.Errorf("refusing to export to terminal; pass a file path or redirect stdout")
}
// proceed with store.Export + writeTo

Prevention

When it happens

Trigger: Running `docker context export <name> -` from an interactive shell where stdout is attached to a TTY, with no pipe or redirection in place.

Common situations: A user copies a pipeline-oriented command (intended as `docker context export ctx - | tar -tv`) but forgets the consuming command, leaving stdout pointing at the terminal; running export interactively to inspect output.

Related errors


AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07). Data as JSON: /api/errors/c3384fa8e6f192aa. Report an issue: GitHub.

Appendix: source

Thrown at cli/command/context/export.go:40

			var dest string
			if len(args) == 2 {
				dest = args[1]
			} else {
				dest = contextName + ".dockercontext"
			}
			return runExport(dockerCLI, contextName, dest)
		},
		ValidArgsFunction:     completeContextNames(dockerCLI, 1, true),
		DisableFlagsInUseLine: true,
	}
}

func writeTo(dockerCli command.Cli, reader io.Reader, dest string) error {
	var writer io.Writer
	var printDest bool
	if dest == "-" {
		if dockerCli.Out().IsTerminal() {
			return errors.New("cowardly refusing to export to a terminal, specify a file path")
		}
		writer = dockerCli.Out()
	} else {
		f, err := os.OpenFile(dest, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0o600)
		if err != nil {
			return err
		}
		defer f.Close()
		writer = f
		printDest = true
	}
	if _, err := io.Copy(writer, reader); err != nil {
		return err
	}
	if printDest {
		fmt.Fprintf(dockerCli.Err(), "Written file %q\n", dest)
	}
	return nil

View on GitHub (pinned to 4f84911bfe)