Markdown rendering silently disabled for entire message when first 500 chars contain no markdown character (Duy/Huy 500-char sniff window)

Open 💬 0 comments Opened Jul 13, 2026 by asgeirtj

Summary

If an assistant message's first 500 characters contain no ASCII markdown character, no URL, and no paragraph break, the entire message is displayed as plain text — all markdown later in the message (bold, lists, italics) shows as raw **asterisks**.

This happens with perfectly normal prose: an opening paragraph of ~510+ characters that uses em-dashes () instead of hyphens and contains no list/backtick/bracket characters is enough to trip it. The model writes long markdown-free opening paragraphs regularly, so this fires in real conversations (that's how we found it).

Environment

  • Claude Code 2.1.207 (native install, macOS arm64, Darwin 25.5.0)
  • Stock binary, default settings

Root cause

From the 2.1.207 binary (minified names as shipped):

Huy = /[#*`|[>\-_~]|\n\n|(?:^|\n) {0,3}\d+\. |https?:\/\/|www\./
function Duy(e){ return Huy.test(e.length > 500 ? e.slice(0, 500) : e) }
function osd(e,t=!0){ if(!Duy(e)) return [{ /* plain text block */ ...

Duy decides "is this markdown?" by testing the regex against only the first 500 characters. A long opening paragraph of clean prose has its first \n\n beyond position 500, em-dashes don't match \-, and quotes/colons/apostrophes match nothing — so the whole message falls into the plain-text path even though it contains **bold**, bullet lists, etc. further down.

Reproduction

Have the assistant output a message that begins with a >510-char paragraph of plain prose (no hyphens, no lists, no URLs — em-dashes are fine since they don't match the regex), followed by markdown:

The harbor town woke slowly under a grey sky, and the fishing boats rocked gently against their moorings while gulls circled the pier in wide lazy loops. Down by the old warehouse the first trucks of the morning were already loading crates of ice, and the drivers stood around with coffee cups steaming in the cold air, talking about the weather and the price of fuel and whether the season would turn out better than the last one, which everyone agreed had been disappointing in almost every way that mattered. Later in the day the wind picked up from the north and the smaller boats came back early, their crews hauling nets onto the dock while the older men watched quietly from the doorway of the bait shop. Detector: bold

Actual: the whole message renders as plain text — **bold** shows literal asterisks.
Expected: markdown renders (or at minimum, the later markdown does).

Conversely, the same message with one short sentence prepended renders fine, because the prepended sentence pulls a \n\n inside the 500-char window — which is what made this so confusing to debug from the outside.

Suggested fix

Any of:

  • Scan the entire text (or first N KB) instead of the first 500 chars — the regex is cheap;
  • Treat / (em/en dash) or : prose as insufficient signal but keep scanning until the first \n\n before deciding;
  • Decide per-paragraph rather than per-message, so a plain opening paragraph doesn't force the whole message raw.

Happy to provide the full bisection log — we verified each element (length, quotes, em-dashes, specific wording) independently before pulling the check out of the binary.

View original on GitHub ↗