[BUG] Whole message renders as raw markdown when the first markdown construct starts after character ~500

Status Open
Reported on v2.1.233
Maintainer reply None cached
Activity 1 comment · opened Aug 16, 2026

Root cause of the intermittent "entire message shown as raw markdown" reports (supersedes my earlier analysis in #73322).

Summary

Claude Code decides whether an assistant message should be markdown-rendered by scanning only the first ~500 characters. If the first markdown construct (**, #, |, ---, list marker, …) starts at offset 500 or later, the entire message is displayed as raw markdown source — literal **bold**, ## headings, |---| table rows.

Found by automated delta-debugging (ddmin) of a real affected message against a headless repro harness; the boundary is exact:

  • first construct at offset 499 → message renders normally
  • first construct at offset 500 → whole message renders raw

Deterministic repro (any renderer, any terminal)

Ask Claude to output a message that begins with ≥500 characters of plain prose (no markdown at all) followed by any markdown, e.g.:

Output one message: first a single plain-prose paragraph of at least 520 characters containing no markdown characters whatsoever, then a paragraph containing bold and a small table.

The whole message — including the markdown tail — displays as raw source. Shorten the plain opening below 500 characters and it renders perfectly. Reproduces identically via --resume re-rendering (which is what makes affected messages permanently raw in the transcript: every redraw makes the same decision).

Verified properties

  • Renderer-independent: reproduces on both the default and fullscreen (CLAUDE_CODE_NO_FLICKER=1) renderers (2.1.233, macOS 26, WezTerm; previously also seen in Ghostty).
  • Deterministic per message content — explains why affected messages stay raw across Ctrl+O transcript view, /tui switches, and --resume in a fresh process, while the next message in the same session can render fine.
  • Terminal exonerated: wezterm cli get-text --escapes shows the affected lines reach the terminal with no styling — the client emits unrendered text.
  • 4/4 prediction accuracy on real transcript messages (three raw, one rendered) by computing the first-construct offset alone.

Why some users hit this constantly and others never do

Any user whose output conventions produce a long markdown-free opening (e.g. a CLAUDE.md instruction to start every response with a plain-prose spoken/summary paragraph for TTS) crosses the 500-char boundary regularly. Default assistant style almost always emits bold/headings early, which masks the bug — likely why this went unreported.

Expected

The markdown decision should consider the whole message (or always render markdown), not a 500-char prefix — per CommonMark, trailing constructs are still markdown regardless of how much plain prose precedes them.

Environment: Claude Code 2.1.233, macOS 26, WezTerm (also Ghostty), zsh.

View original on GitHub ↗

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