A0 CLI crashes with Rich/Textual MarkupError when chat log contains path-like bracket markup
## Summary
The macOS A0 CLI crashes while rendering or handling chat/context events when the chat log contains path-like text that appears to be interpreted as Rich/Textual markup.
The first visible error is a `MarkupError` caused by a string such as `[/a0/tests/test_a0_connector_prompt_gatin]` being interpreted as a closing Rich markup tag. After that, the CLI repeatedly raises `textual.css.query.NoMatches` because `#chat-log` can no longer be found on the active screen.
This appears to be a local A0 CLI UI/rendering issue, not a Caddy, HTTPS, or WebSocket transport issue.
---
## Environment
| Item | Value |
|---|---|
| Client OS | macOS |
| CLI package | `agent_zero_cli` |
| Python runtime | Python 3.11 |
| CLI path shown in traceback | `/Users/ncc1701dhs/.local/share/uv/tools/a0/lib/python3.11/site-packages/agent_zero_cli/...` |
| Agent Zero server | Docker/Linux container |
| Access URL / FQDN | `https://ai-agent.ailab.tokyo` |
| Reverse proxy | Caddy |
| Connector transport | HTTP + WebSocket / Socket.IO |
| A0 connector API | `/api/plugins/_a0_connector/v1/capabilities` |
---
## What was confirmed
The connector capability endpoint responds successfully over HTTPS through Caddy.
```http
POST https://ai-agent.ailab.tokyo/api/plugins/_a0_connector/v1/capabilities
HTTP/2 200
```
The returned capabilities include:
```json
{
"protocol": "a0-connector.v1",
"auth": ["session"],
"auth_required": true,
"transports": ["http", "websocket"],
"streaming": true,
"websocket_namespace": "/ws",
"websocket_handlers": ["plugins/_a0_connector/ws_connector"],
"features": [
"chat_create",
"chats_list",
"chat_get",
"message_send",
"log_tail",
"projects",
"text_editor_remote",
"code_execution_remote",
"computer_use_remote",
"remote_file_tree"
]
}
```
The Web UI WebSocket also appears to work through Caddy. Browser DevTools showed frames like:
```text
42/ws,["state_push",{"handlerId":"ws_webui.WsWebui", ... }]
```
So the issue does not appear to be a general HTTPS/WSS/Caddy forwarding failure.
---
## Actual behavior
After receiving/rendering chat log content that included long paths and bracket-like strings, the A0 CLI printed the following error:
```text
MarkupError: closing tag '[/a0/tests/test_a0_connector_prompt_gatin]' does not match any open tag
```
Then repeated task exceptions appeared:
```text
Task exception was never retrieved
future: <Task finished name='Task-5678' coro=<AsyncClient._handle_eio_message() done, defined at /Users/ncc1701dhs/.local/share/uv/tools/a0/lib/python3.11/site-packages/socketio/async_client.py:563> exception=NoMatches("No nodes match '#chat-log' on Screen(id='_default')")>
Traceback (most recent call last):
File "/Users/ncc1701dhs/.local/share/uv/tools/a0/lib/python3.11/site-packages/socketio/async_client.py", line 580, in _handle_eio_message
await self._handle_event(pkt.namespace, pkt.id, pkt.data)
File "/Users/ncc1701dhs/.local/share/uv/tools/a0/lib/python3.11/site-packages/socketio/async_client.py", line 417, in _handle_event
r = await self._trigger_event(data[0], namespace, *data[1:])
File "/Users/ncc1701dhs/.local/share/uv/tools/a0/lib/python3.11/site-packages/socketio/async_client.py", line 472, in _trigger_event
ret = await handler(*args)
File "/Users/ncc1701dhs/.local/share/uv/tools/a0/lib/python3.11/site-packages/agent_zero_cli/client.py", line 381, in _on_context_event
callback(self._unwrap_envelope(payload))
File "/Users/ncc1701dhs/.local/share/uv/tools/a0/lib/python3.11/site-packages/agent_zero_cli/connection.py", line 240, in <lambda>
app.client.on_context_event = lambda data: app._run_on_ui(app._handle_context_event, data)
File "/Users/ncc1701dhs/.local/share/uv/tools/a0/lib/python3.11/site-packages/agent_zero_cli/app.py", line 909, in _run_on_ui
func(*args)
File "/Users/ncc1701dhs/.local/share/uv/tools/a0/lib/python3.11/site-packages/agent_zero_cli/app.py", line 1051, in _handle_context_event
event_handlers.handle_context_event(self, data)
File "/Users/ncc1701dhs/.local/share/uv/tools/a0/lib/python3.11/site-packages/agent_zero_cli/event_handlers.py", line 78, in handle_context_event
log = app.query_one("#chat-log", ChatLog)
File "/Users/ncc1701dhs/.local/share/uv/tools/a0/lib/python3.11/site-packages/textual/dom.py", line 1505, in query_one
raise NoMatches(f"No nodes match {query_selector!r} on {base_node!r}")
textual.css.query.NoMatches: No nodes match '#chat-log' on Screen(id='_default')
```
The `NoMatches('#chat-log')` exception repeats for subsequent context events.
---
## Expected behavior
The CLI should display chat/log content as literal text, even if it contains strings like:
```text
[/a0/tests/test_a0_connector_prompt_gating.py]
/a0/plugins/_a0_connector/...
```
Such content should not be interpreted as Rich/Textual markup.
The CLI should not crash, and context event handling should continue normally.
---
## Suspected cause
The CLI appears to pass chat/log content to Rich/Textual without escaping markup-sensitive characters.
A path-like or log-like string containing square brackets may be interpreted as Rich markup. In this case, a substring like:
```text
[/a0/tests/test_a0_connector_prompt_gatin]
```
seems to be parsed as a closing tag, causing:
```text
rich.errors.MarkupError: closing tag ... does not match any open tag
```
After the initial render failure, the Textual screen/component tree appears to enter an invalid state, causing `app.query_one("#chat-log", ChatLog)` to fail with:
```text
NoMatches("No nodes match '#chat-log' on Screen(id='_default')")
```
---
## Why this looks like a CLI rendering issue, not a transport issue
The following transport checks were successful:
- HTTPS endpoint through Caddy returns `HTTP/2 200`.
- Connector capabilities include `http` and `websocket` transports.
- Web UI WebSocket frames are visible, including `state_push` from `ws_webui.WsWebui`.
- The CLI shows connection to the expected host: `https://ai-agent.ailab.tokyo`.
Therefore, the WebSocket/Caddy path appears functional. The crash happens in the local CLI UI stack while handling/rendering context events.
---
## Possible fix
Escape chat/log/message content before rendering it with Rich/Textual.
For example, use Rich markup escaping around any untrusted or server-provided text before passing it to a Rich renderable:
```python
from rich.markup import escape
safe_text = escape(raw_text)
```
Any content from chat messages, logs, tool output, file paths, traceback text, and server-sent context events should be treated as untrusted display text unless intentionally formatted.
Also, `handle_context_event()` could defensively handle the case where `#chat-log` is not mounted yet or no longer exists, instead of allowing repeated uncaught task exceptions.
Potential places from the traceback:
```text
agent_zero_cli/event_handlers.py:78
agent_zero_cli/app.py:1051
agent_zero_cli/app.py:909
agent_zero_cli/connection.py:240
agent_zero_cli/client.py:381
```
---
## Workaround
Temporary workarounds:
1. Restart the A0 CLI fully.
2. Avoid opening the affected chat/context in the CLI if it contains the problematic log text.
3. Use a new chat/context after restarting the CLI.
4. Avoid sending very long raw logs or path-heavy output to the CLI until the rendering is fixed.
5. Use the Web UI to inspect the problematic chat if the CLI crashes during render.
---
## Additional context
This was observed while debugging A0 CLI Connector remote tool exposure. Remote file-tree or connector metadata may appear, but `code_execution_remote`, `text_editor_remote`, or `computer_use_remote` may not become usable if the CLI UI crashes while processing context events.
A search did not find an exact existing Agent Zero issue for this `MarkupError` + `#chat-log` combination. Similar Rich CLI crashes caused by unescaped bracketed text have been reported in other CLI projects, so this may be a general Rich/Textual escaping issue pattern.
---
## Short version for maintainers
A0 CLI should probably escape untrusted chat/log output before rendering with Rich/Textual. A path-like string was interpreted as a Rich closing tag, causing `MarkupError`, after which the CLI repeatedly failed to find `#chat-log` while handling Socket.IO context events.
2 条评论