docker/compose · error

--tty and --no-tty can't be used together

Error message

--tty and --no-tty can't be used together

What it means

`docker compose run` has both `--tty` and `--no-tty` flags; setting both in the same invocation is rejected because they directly contradict. The check uses Flags().Changed so even `--tty=false --no-tty=false` (both explicitly set) triggers the error.

Source

Thrown at cmd/compose/run.go:182

		Args:  cobra.MinimumNArgs(1),
		PreRunE: AdaptCmd(func(ctx context.Context, cmd *cobra.Command, args []string) error {
			options.Service = args[0]
			if len(args) > 1 {
				options.Command = args[1:]
			}
			if len(options.publish) > 0 && options.servicePorts {
				return fmt.Errorf("--service-ports and --publish are incompatible")
			}
			if cmd.Flags().Changed("entrypoint") {
				command, err := shellwords.Parse(options.entrypoint)
				if err != nil {
					return err
				}
				options.entrypointCmd = command
			}
			if cmd.Flags().Changed("tty") {
				if cmd.Flags().Changed("no-tty") {
					return fmt.Errorf("--tty and --no-tty can't be used together")
				} else {
					options.noTty = !ttyFlag
				}
			} else if !cmd.Flags().Changed("no-tty") && !cmd.Flags().Changed("interactive") && !dockerCli.In().IsTerminal() {
				// while `docker run` requires explicit `-it` flags, Compose enables interactive mode and TTY by default
				// but when compose is used from a script that has stdin piped from another command, we just can't
				// Here, we detect we run "by default" (user didn't passed explicit flags) and disable TTY allocation if
				// we don't have an actual terminal to attach to for interactive mode
				options.noTty = true
			}

			if options.quiet {
				display.Mode = display.ModeQuiet
				backendOptions.Add(compose.WithEventProcessor(display.Quiet()))
			}
			createOpts.pullChanged = cmd.Flags().Changed("pull")
			return nil
		}),

View on GitHub (pinned to ddc4b044b6)

Solutions

  1. Pass exactly one of `--tty` or `--no-tty`.
  2. Rely on compose's auto-detection: with no flags it enables TTY only when stdin is a terminal.
  3. In scripts, branch on a single boolean and emit only the corresponding flag.

Example fix

# before
docker compose run --tty --no-tty web sh

# after
docker compose run --no-tty web sh
Defensive patterns

Strategy: validation

Validate before calling

# bash: single tty policy
TTY_ARGS=()
case "${TTY_MODE:-auto}" in tty) TTY_ARGS=(--tty);; no-tty) TTY_ARGS=(--no-tty);; auto) ;; *) echo "tty mode must be tty|no-tty|auto" >&2; exit 2;; esac
docker compose run "${TTY_ARGS[@]}" web

Prevention

When it happens

Trigger: Running `docker compose run --tty --no-tty web`, or any invocation where both flags appear on the command line regardless of their values.

Common situations: Scripts templating both flags from independent booleans (`--tty=$TTY --no-tty=$NOTTY`); users adding --no-tty for piped input while --tty is already set by an alias or wrapper.

Related errors


AI-assisted analysis of docker/compose@ddc4b044b6 (2026-08-15). Data as JSON: /api/errors/a41af5ac3cfe3c5f. Report an issue: GitHub.