basecamp/kamal · error · ArgumentError

Raw is not compatible with interactive

Error message

Raw is not compatible with interactive

What it means

`kamal accessory exec NAME CMD` runs a command inside an accessory's container. The --raw flag makes Kamal print the command's stdout unmodified (for scripting/piping), while -i/--interactive attaches an interactive SSH session for shells like bash/console. These modes are mutually exclusive because raw output capture cannot coexist with a TTY-attached interactive session, so Kamal raises ArgumentError before connecting to any host.

Source

Thrown at lib/kamal/cli/accessory.rb:154

    if name == "all"
      KAMAL.accessory_names.each { |accessory_name| details(accessory_name) }
    else
      type = "Accessory #{name}"
      with_accessory(name) do |accessory, hosts|
        on(hosts) { puts_by_host host, capture_with_info(*accessory.info), type: type, quiet: quiet }
      end
    end
  end

  desc "exec [NAME] [CMD...]", "Execute a custom command on servers within the accessory container (use --help to show options)"
  option :interactive, aliases: "-i", type: :boolean, default: false, desc: "Execute command over ssh for an interactive shell (use for console/bash)"
  option :reuse, type: :boolean, default: false, desc: "Reuse currently running container instead of starting a new one"
  option :raw, type: :boolean, default: false, desc: "Output raw, unmodified stdout"
  def exec(name, *cmd)
    raw = options[:raw]

    if raw && options[:interactive]
      raise ArgumentError, "Raw is not compatible with interactive"
    end

    with_raw_output(raw) do
      pre_connect_if_required

      cmd = Kamal::Utils.join_commands(cmd)
      quiet = options[:quiet]

      with_accessory(name) do |accessory, hosts|
        case
        when options[:interactive] && options[:reuse]
          say "Launching interactive command via SSH from existing container...", :magenta
          run_locally { exec accessory.execute_in_existing_container_over_ssh(cmd) }

        when options[:interactive]
          say "Launching interactive command via SSH from new container...", :magenta
          on(accessory.hosts.first) { execute *KAMAL.registry.login }
          run_locally { exec accessory.execute_in_new_container_over_ssh(cmd) }

View on GitHub (pinned to eee0083b38)

Solutions

  1. Drop one of the two flags: use `kamal accessory exec NAME -i bash` for a shell, or `kamal accessory exec NAME --raw CMD` for clean pipeable output.
  2. If you need to capture output of an interactive-only program, run it non-interactively without -i and keep --raw.
  3. Check shell aliases/scripts that inject flags automatically and remove the conflicting one.

Example fix

# before
kamal accessory exec mysql --raw -i bash
# after
kamal accessory exec mysql -i bash
# or, for scriptable output:
kamal accessory exec mysql --raw mysqladmin ping
Defensive patterns

Strategy: validation

Validate before calling

raw = ARGV.include?("--raw")
interactive = ARGV.include?("-i") || ARGV.include?("--interactive")
abort "--raw and -i are mutually exclusive" if raw && interactive
# then invoke: kamal accessory exec #{ARGV.join(' ')}

Try / catch

begin
  # programmatic invocation
  Kamal::CLI::Accessory.new.invoke(:exec, [ "mysql", "mysqladmin", "ping" ], raw: true)
rescue ArgumentError => e
  raise unless e.message.include?("not compatible")
  warn "flag conflict: #{e.message}" # strip -i or --raw and retry once
end

Prevention

When it happens

Trigger: Running `kamal accessory exec mysql --raw -i bash`, or any invocation where both options[:raw] and options[:interactive] are truthy, e.g. flags set in a shell alias or a script that always passes -i. Raised immediately in the exec method, before with_raw_output and before any SSH connection.

Common situations: Copy-pasting a console command from docs that uses -i while a wrapper script adds --raw to strip Kamal's log noise; aliases like `alias mysql-console='kamal accessory exec mysql -i --raw'`; piping output (`--raw`) while forgetting to remove -i from a previous command line.

Related errors


AI-assisted analysis of basecamp/kamal@eee0083b38 (2026-08-21). Data as JSON: /api/errors/7b037ebd89cedfbc. Report an issue: GitHub.