When pi-coding-agent renders a streaming response containing a Markdown table with cells that include inline markup (e.g. 🛒 **Marketplace**), it calls font-lock-ensure on a temporary md-ts-mode buffer. If md-ts-mode's tree-sitter font-lock rules throw a treesit-query-error, the exception propagates uncaught up through the streaming render pipeline, breaking the rest of the response display.
The user sees the response truncated mid-table, with subsequent content missing from the chat buffer.
Environment
|
|
| Emacs |
30.2 |
| pi-coding-agent |
20260405.21 |
| md-ts-mode |
20260309.11 |
| tree-sitter system library |
0.26.8 |
| Model |
glm-5.1 via ZAI (openai-completions provider) |
Steps to Reproduce
- Start a new pi-coding-agent chat session with a model that produces rich Markdown tables (e.g.
glm-5.1 via ZAI).
- Send a prompt that triggers a response containing a table with bold text or emoji in cells:
Search for a file in ~/dev/myproject/, read it, and summarize it.
- Observe the response is cut off mid-table in the chat buffer.
- Check
*Messages* for the error — with debug-on-error t the full backtrace is:
Debugger entered--Lisp error: (treesit-query-error "Syntax error at" 136
"(block_quote) @md-ts-block-quote ..."
"Debug the query with `treesit-query-validate'")
treesit--font-lock-fontify-region-1(...)
treesit-font-lock-fontify-region(1 18 nil)
font-lock-ensure()
pi-coding-agent--markdown-visible-string("🛒 **Marketplace**")
pi-coding-agent--table-display-groups(...)
pi-coding-agent--decorate-table(...)
pi-coding-agent--maybe-decorate-streaming-table()
pi-coding-agent--display-message-delta(" |\n")
pi-coding-agent--handle-display-event(...)
Root Cause
pi-coding-agent--markdown-visible-string (in pi-coding-agent-table.el) creates a persistent buffer in md-ts-mode and calls font-lock-ensure to extract the visible text of a table cell:
(defun pi-coding-agent--markdown-visible-string (markdown)
...
(with-current-buffer (pi-coding-agent--visible-string-buffer)
(let ((inhibit-read-only t))
(erase-buffer)
(insert markdown))
(font-lock-ensure) ; <-- can throw treesit-query-error
(pi-coding-agent--visible-text (point-min) (point-max))))
font-lock-ensure is called without any error handling. When md-ts-mode's paragraph/prepend tree-sitter query fails at the C level (a known incompatibility between Emacs 30 treesit.c generating #match and tree-sitter 0.25+ requiring #match?), the exception escapes into pi-coding-agent--display-message-delta, silently aborting the render of the current and all subsequent streaming deltas.
Note: the same treesit-query-error also appears as Error during redisplay: (jit-lock-function ...) in the main chat buffer — that is a separate manifestation of the same md-ts-mode query bug (reported independently at https://github.com/dnouri/md-ts-mode/issues/XXX).
Proposed Fix
Wrap font-lock-ensure in a condition-case and fall back to returning the raw markdown string on error. This makes the function resilient to any font-lock failure, not just this specific md-ts-mode query issue:
(defun pi-coding-agent--markdown-visible-string (markdown)
...
(with-current-buffer (pi-coding-agent--visible-string-buffer)
(let ((inhibit-read-only t))
(erase-buffer)
(insert markdown))
;; Guard against treesit-query-error or other font-lock failures
;; (e.g. md-ts-mode query incompatibility with tree-sitter 0.25+).
;; On failure, fall back to the raw markdown string.
(condition-case _err
(font-lock-ensure)
(error nil))
(pi-coding-agent--visible-text (point-min) (point-max))))
The fallback is safe: pi-coding-agent--visible-text still returns a reasonable string (the raw markdown with delimiters visible), which is better than crashing the render pipeline entirely.
Additional Notes
- The bug is not model-specific in principle, but in practice it is triggered more frequently by models like
glm-5.1 (ZAI) that tend to produce tables with rich inline markup (bold + emoji) in cells. Models that generate plain-text table cells never hit this code path.
- The
treesit-query-error only fires when md-ts-mode is the active mode in the fontification buffer and the installed tree-sitter library is 0.25+. Users on older tree-sitter versions are unaffected.
- A fix to
md-ts-mode itself (removing the broken :match predicate) eliminates the root cause entirely. This defensive fix in pi-coding-agent is recommended regardless, as it protects against any future font-lock errors from any mode used in the fontification buffer.
When
pi-coding-agentrenders a streaming response containing a Markdown table with cells that include inline markup (e.g.🛒 **Marketplace**), it callsfont-lock-ensureon a temporarymd-ts-modebuffer. Ifmd-ts-mode's tree-sitter font-lock rules throw atreesit-query-error, the exception propagates uncaught up through the streaming render pipeline, breaking the rest of the response display.The user sees the response truncated mid-table, with subsequent content missing from the chat buffer.
Environment
glm-5.1via ZAI (openai-completionsprovider)Steps to Reproduce
glm-5.1via ZAI).*Messages*for the error — withdebug-on-error tthe full backtrace is:Root Cause
pi-coding-agent--markdown-visible-string(inpi-coding-agent-table.el) creates a persistent buffer inmd-ts-modeand callsfont-lock-ensureto extract the visible text of a table cell:font-lock-ensureis called without any error handling. Whenmd-ts-mode'sparagraph/prependtree-sitter query fails at the C level (a known incompatibility betweenEmacs 30 treesit.cgenerating#matchandtree-sitter 0.25+requiring#match?), the exception escapes intopi-coding-agent--display-message-delta, silently aborting the render of the current and all subsequent streaming deltas.Note: the same
treesit-query-erroralso appears asError during redisplay: (jit-lock-function ...)in the main chat buffer — that is a separate manifestation of the samemd-ts-modequery bug (reported independently at https://github.com/dnouri/md-ts-mode/issues/XXX).Proposed Fix
Wrap
font-lock-ensurein acondition-caseand fall back to returning the raw markdown string on error. This makes the function resilient to any font-lock failure, not just this specificmd-ts-modequery issue:The fallback is safe:
pi-coding-agent--visible-textstill returns a reasonable string (the raw markdown with delimiters visible), which is better than crashing the render pipeline entirely.Additional Notes
glm-5.1(ZAI) that tend to produce tables with rich inline markup (bold + emoji) in cells. Models that generate plain-text table cells never hit this code path.treesit-query-erroronly fires whenmd-ts-modeis the active mode in the fontification buffer and the installed tree-sitter library is 0.25+. Users on older tree-sitter versions are unaffected.md-ts-modeitself (removing the broken:matchpredicate) eliminates the root cause entirely. This defensive fix inpi-coding-agentis recommended regardless, as it protects against any future font-lock errors from any mode used in the fontification buffer.