[BUG] TUI crash: MarkupError in ApprovalDialog when content contains "[tag=value:" pattern

Resolved 💬 1 comment Opened May 2, 2026 by rosangmin-code Closed Jun 2, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Summary

ApprovalDialog (Textual) crashes with rich.errors.MarkupError when the content being approved contains text that resembles Rich/Textual markup tags ([name=value] style). The widget appears to render user-supplied content with markup=True instead of escaping [ or passing markup=False.

Environment

  • Claude Code: 2.1.126
  • OS: Linux 6.17.0-20-generic (Ubuntu 24.04)
  • Python: 3.12.3
  • textual: 8.2.4
  • rich: 15.0.0

Reproduction

Create a file with bracket-prefixed lines that look like markup tags:

print(f"[stage] item count = {n}")
print(f"[stage] other count = {m}")

Trigger any tool call that surfaces this content in the approval dialog
(Read / Edit / a Bash command whose preview includes the text). The dialog crashes during layout in _compositor.reflow.

Expected

Dialog renders the content as plain text — [stage], =, etc. .

Actual

MarkupError: Expected markup value (found '=<token>:\n').

Traceback (relevant frames):

textual/screen.py:1354 in _refresh_layout
  → textual/_compositor.py:387 in reflow
  → textual/_compositor.py:744 in _arrange_root
  → textual/_compositor.py:601 in add_widget
  → textual/screen.py:543 in arrange
  → textual/_arrange.py:97 in arrange
  → textual/layouts/vertical.py:53 in arrange
  → textual/_resolve.py:254 in resolve_box_models
  → textual/widget.py:1838 in _get_box_model
  → textual/widget.py:1939 in get_content_height
  → textual/widget.py:4471 in _render
  → textual/widgets/_static.py:83 in render
  → textual/widgets/_static.py:62 in visual
    visualize(self, self.__content, markup=self._render_markup)
                                          ^^^^^^^^^^^^^^^^^^^^^

The crashing widget is Static() inside ApprovalDialog → Vertial-from-member, PromptOptionsTable, Static#approval-auto-hint,Static]. _render_markup is True, so any [ in user content is treated as markup.

Suspected fix

In the Static(...) constructions inside ApprovalDialog (and der user-provided text — tool result preview, prompt body, etc.),either:

  1. Pass markup=False, or
  2. Pre-escape with rich.markup.escape(text) before passing to

Either approach renders [tag=value] content literally and avoi

Frequency

Reliably reproducible. Occurs whenever the approval dialog body contains [tag=value]-shaped substrings — common in:

  • Python print statements with bracketed log prefixes
  • Markdown notes quoting such code
  • Any CLI output reproduced as a code block

In affected projects the crash recurs every few tool calls untile.

What Should Happen?

Expected

Dialog renders the content as plain text — [stage], =, etc. should be displayed verbatim.

Error Messages/Logs

Traceback (relevant frames):

textual/screen.py:1354 in _refresh_layout
  → textual/_compositor.py:387 in reflow
  → textual/_compositor.py:744 in _arrange_root
  → textual/_compositor.py:601 in add_widget
  → textual/screen.py:543 in arrange
  → textual/_arrange.py:97 in arrange
  → textual/layouts/vertical.py:53 in arrange
  → textual/_resolve.py:254 in resolve_box_models
  → textual/widget.py:1838 in _get_box_model
  → textual/widget.py:1939 in get_content_height
  → textual/widget.py:4471 in _render
  → textual/widgets/_static.py:83 in render
  → textual/widgets/_static.py:62 in visual
    visualize(self, self.__content, markup=self._render_markup)
                                          ^^^^^^^^^^^^^^^^^^^^^

Steps to Reproduce

Suspected fix

In the Static(...) constructions inside ApprovalDialog (and any sibling widgets that render user-provided text — tool result preview, prompt body, etc.), either:

  1. Pass markup=False, or
  2. Pre-escape with rich.markup.escape(text) before passing to Static.

Either approach renders [tag=value] content literally and avoids the parser path entirely.

Frequency

Reliably reproducible. Occurs whenever the approval dialog body contains [tag=value]-shaped substrings — common in:

  • Python print statements with bracketed log prefixes
  • Markdown notes quoting such code
  • Any CLI output reproduced as a code block

In affected projects the crash recurs every few tool calls until those files are out of scope.

Claude Model

Opus

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.126

Platform

Anthropic API

Operating System

Ubuntu/Debian Linux

Terminal/Shell

VS Code integrated terminal

Additional Information

_No response_

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗