Skip to content

aider --message '<slash-command>' silently does nothing and exits 0 (SwitchCoder swallowed) #5623

Description

@aniruddhaadak80

Issue

Summary

When aider is driven headlessly with --message, any input that starts with / is processed as an in-chat command — and several of those commands (/model, /editor-model, /weak-model, /chat-mode, /ask, /code, /architect, ...) work by raising SwitchCoder. In main() that exception is swallowed with a bare pass, so aider prints its banner and exits 0 having done nothing:

aider/main.py:

if args.message:
    io.add_to_input_history(args.message)
    io.tool_output()
    try:
        coder.run(with_message=args.message)
    except SwitchCoder:
        pass
    analytics.event("exit", reason="Completed --message")
    return

The command never runs, the message is never sent, and nothing tells the user or the calling script what happened. Compare with the interactive loop, which properly handles SwitchCoder by rebuilding the coder (main.py while True: / except SwitchCoder as switch:).

Reproduction (verified on current main)

$ aider --message "/model gpt-4o" --no-git --yes-always
Aider v0.86.3.dev53+g5dc9490bb
Main model: gpt-4o-mini ...   <- original model, unchanged
...
EXITCODE=0

No error, no warning, exit code 0. The requested model switch silently did not happen.

The same happens for every SwitchCoder-raising command passed via --message, including the very common scripting pattern:

  • aider --message "/ask explain this module" → silent no-op, exit 0
  • aider --message "/architect refactor X" → silent no-op, exit 0

(commands.py raises SwitchCoder from cmd_model, cmd_editor_model, cmd_weak_model, cmd_chat_mode, cmd_ask, cmd_code, cmd_architect.)

Impact

Headless/CI users can't distinguish "command executed" from "input ignored" — both exit 0. This is the same class of headless trap as #5552 (exit 0 after fatal API errors) but a different mechanism and location: here the swallow is explicit at main.py's --message branch.

Note the adjacent --message-file path has open PRs handling SwitchCoder; the plain --message branch still discards it.

Expected behavior

Either:

  1. Apply the switch like the interactive loop does (rebuild the coder and continue with the remaining message), if anything follows the command; or at minimum
  2. Print a clear error ("/model is only supported in interactive mode") and exit non-zero, mirroring what /load does for nested switches (commands.py: "Command '...' is only supported in interactive mode, skipping.").

Happy to send a PR implementing option 2 (small, safe) or option 1.

Version and model info

  • Aider v0.86.3.dev53+g5dc9490bb (main @ 5dc9490bb)
  • Python 3.12.10, Windows 11; behavior is platform-independent
  • Any model; triggered purely by CLI argument + in-chat command combination

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions