Environment
- Linux (Ubuntu)
- LM Studio 0.4.6
- Models: qwen/qwen3.5-35b-a3b, qwen3.5-27b (both reproduce)
- MCP tools connected (webfetch-mcp with web_search/web_fetch)
What is the bug?
LM Studio's tool call parser scans the content inside <think> blocks for tool call patterns (<function=...>, <tool_call>, <tool_call_start|>). When the model reasons about tool calling syntax as prose, the parser interprets those text patterns as actual tool call attempts, which then fail to parse.
This is distinct from #1589 and #827, where <think> tags break tool call output. Here, the parser actively enters the thinking block and finds false positives.
Reproduction
- Load qwen3.5-35b-a3b with reasoning enabled
- Connect any MCP tool (e.g., web_search)
- Give the model a task that causes it to reason about tool calling — e.g., debugging a tool call format issue, or researching how different models handle tool calls
- The model's thinking block will mention tool call syntax as prose (e.g., "some models use
<function=...>, others use <tool_call>")
- Parser picks up these prose mentions as tool call attempts → parse failure
Observed behavior
The parser treats reasoning-block prose like:
<think>
...LM Studio's parser is treating <tool_call_start|> as raw text instead of
recognizing it as a special token that should trigger tool call parsing...
</think>
as containing actual tool call markers. The </think> boundary is not respected as a parsing firewall.
Recursive trap
This creates a self-referential failure loop:
- Model reasons about tool call syntax → emits tool-call-like tokens in
<think> block
- Parser finds them → parse fails (they're prose, not well-formed calls)
- Error fed back to model → model reasons about the parse failure → mentions more tool call syntax
- Goto 2
The model explicitly recognizes the trap ("I'm getting caught in a loop where my thoughts about tool calling syntax are being interpreted as actual tool call markers") but cannot escape it — reasoning about the problem reproduces it.
Multiple format matching widens false-positive surface
The parser appears to scan for multiple tool call formats simultaneously (<tool_call>, <function=...>, <tool_call_start|>). When the model discusses format differences between models (e.g., Qwen's <tool_call> vs LFM2.5's <tool_call_start|> vs <function=...>), multiple patterns trigger in a single thinking block.
Expected behavior
The </think> boundary should be a firewall — everything between <think> and </think> should be treated as reasoning text, not scanned for tool call patterns. Ollama handles this correctly by stripping reasoning tags before tool call parsing (as noted in #1589).
Workaround
Disabling reasoning via {%- set enable_thinking = false %} in the prompt template eliminates the issue. 20+ consecutive tool calls succeed with reasoning disabled.
Evidence
Parse failure output shows reasoning content flowing into the parsed "tool call":
Failed to parse tool call: Expected "<parameter=", but got "`, `<parame" at index 14.
<tool_call>, some use `<tool_call_start|>`, some use `<function=...>`)
4. LM Studio's parser may not recognize all token formats Let me search
for more specific information... </think> <tool_call>
<function=web_search> <parameter=limit> 10 </parameter>
<parameter=query> LM Studio "reasoning" "tool call" parsing bug scan
thought block </parameter> </function> </tool_call>
The reasoning prose and the actual tool call are concatenated in the parser's view — the </think> boundary was not used as a delimiter.
Related issues
Environment
What is the bug?
LM Studio's tool call parser scans the content inside
<think>blocks for tool call patterns (<function=...>,<tool_call>,<tool_call_start|>). When the model reasons about tool calling syntax as prose, the parser interprets those text patterns as actual tool call attempts, which then fail to parse.This is distinct from #1589 and #827, where
<think>tags break tool call output. Here, the parser actively enters the thinking block and finds false positives.Reproduction
<function=...>, others use<tool_call>")Observed behavior
The parser treats reasoning-block prose like:
as containing actual tool call markers. The
</think>boundary is not respected as a parsing firewall.Recursive trap
This creates a self-referential failure loop:
<think>blockThe model explicitly recognizes the trap ("I'm getting caught in a loop where my thoughts about tool calling syntax are being interpreted as actual tool call markers") but cannot escape it — reasoning about the problem reproduces it.
Multiple format matching widens false-positive surface
The parser appears to scan for multiple tool call formats simultaneously (
<tool_call>,<function=...>,<tool_call_start|>). When the model discusses format differences between models (e.g., Qwen's<tool_call>vs LFM2.5's<tool_call_start|>vs<function=...>), multiple patterns trigger in a single thinking block.Expected behavior
The
</think>boundary should be a firewall — everything between<think>and</think>should be treated as reasoning text, not scanned for tool call patterns. Ollama handles this correctly by stripping reasoning tags before tool call parsing (as noted in #1589).Workaround
Disabling reasoning via
{%- set enable_thinking = false %}in the prompt template eliminates the issue. 20+ consecutive tool calls succeed with reasoning disabled.Evidence
Parse failure output shows reasoning content flowing into the parsed "tool call":
The reasoning prose and the actual tool call are concatenated in the parser's view — the
</think>boundary was not used as a delimiter.Related issues
<think>tags adjacent to JSON break parsing (different: that's about output format, this is about false positives inside thinking blocks)