[PR #15011] model/parsers: fall back to content when qwen tool call XML parse fails #77261

Open
opened 2026-05-05 09:55:59 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/ollama/ollama/pull/15011
Author: @r266-tech
Created: 3/22/2026
Status: 🔄 Open

Base: mainHead: fix/qwen3coder-toolcall-parse-error-fallback


📝 Commits (1)

  • 3b1c54e model/parsers: fall back to content when qwen tool call XML parse fails

📊 Changes

2 files changed (+42 additions, -2 deletions)

View changed files

📝 model/parsers/qwen35_test.go (+32 -0)
📝 model/parsers/qwen3coder.go (+10 -2)

📄 Description

Summary

Fixes #14986

Root Cause

The Qwen3.5 model always has a builtin parser registered (qwen3.5). When a user prompt instructs the model to emit <tool_call>...</tool_call>-style XML as plain text — without registering native Ollama tools — the Qwen3CoderParser still scans for those delimiters in the model output, finds them, and calls parseToolCall().

If the content between the tags is not valid Qwen3-coder XML (e.g. a JSON payload such as {"name": "get_weather", ...}), xml.Unmarshal returns an error (typically EOF). That error propagated all the way up to GenerateHandler / ChatHandler, which sent {"error":"EOF"} and returned HTTP 500.

Fix

In Qwen3CoderParser.Add(), when parseToolCall fails:

  • Before: return the error immediately
  • After: log a warning and write the raw tool-call text (including the wrapping tags) into the content strings.Builder, then break

This means the caller always receives a usable HTTP 200 response with the raw model output instead of an internal server error.

Safety: when real tools are registered and the model produces well-formed Qwen3-coder XML, parseToolCall succeeds and the existing path is taken unchanged.

Changes

  • model/parsers/qwen3coder.go: on parse failure, fall back to content instead of returning an error
  • model/parsers/qwen35_test.go: add regression test that initialises the parser with no tools (matching the /api/generate code path) and feeds it a JSON-style <tool_call> block — expects no error and non-empty content

Testing

New test: TestQwen35ParserToolCallAsPlainTextFallback


CLA Confirmation: I have read, understood, and agree to the Ollama Contributor License Agreement (CLA). I understand that this contribution may be used under the terms of the MIT license.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/ollama/ollama/pull/15011 **Author:** [@r266-tech](https://github.com/r266-tech) **Created:** 3/22/2026 **Status:** 🔄 Open **Base:** `main` ← **Head:** `fix/qwen3coder-toolcall-parse-error-fallback` --- ### 📝 Commits (1) - [`3b1c54e`](https://github.com/ollama/ollama/commit/3b1c54e522c2140af089a146e79949d174ee846a) model/parsers: fall back to content when qwen tool call XML parse fails ### 📊 Changes **2 files changed** (+42 additions, -2 deletions) <details> <summary>View changed files</summary> 📝 `model/parsers/qwen35_test.go` (+32 -0) 📝 `model/parsers/qwen3coder.go` (+10 -2) </details> ### 📄 Description ## Summary Fixes #14986 ## Root Cause The Qwen3.5 model always has a builtin parser registered (`qwen3.5`). When a user prompt instructs the model to emit `<tool_call>...</tool_call>`-style XML as plain text — without registering native Ollama tools — the `Qwen3CoderParser` still scans for those delimiters in the model output, finds them, and calls `parseToolCall()`. If the content between the tags is not valid Qwen3-coder XML (e.g. a JSON payload such as `{"name": "get_weather", ...}`), `xml.Unmarshal` returns an error (typically `EOF`). That error propagated all the way up to `GenerateHandler` / `ChatHandler`, which sent `{"error":"EOF"}` and returned HTTP 500. ## Fix In `Qwen3CoderParser.Add()`, when `parseToolCall` fails: - **Before:** return the error immediately - **After:** log a warning and write the raw tool-call text (including the wrapping tags) into the content `strings.Builder`, then `break` This means the caller always receives a usable HTTP 200 response with the raw model output instead of an internal server error. **Safety:** when real tools are registered and the model produces well-formed Qwen3-coder XML, `parseToolCall` succeeds and the existing path is taken unchanged. ## Changes - `model/parsers/qwen3coder.go`: on parse failure, fall back to content instead of returning an error - `model/parsers/qwen35_test.go`: add regression test that initialises the parser with no tools (matching the `/api/generate` code path) and feeds it a JSON-style `<tool_call>` block — expects no error and non-empty content ## Testing New test: `TestQwen35ParserToolCallAsPlainTextFallback` --- **CLA Confirmation:** I have read, understood, and agree to the Ollama Contributor License Agreement (CLA). I understand that this contribution may be used under the terms of the MIT license. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-05-05 09:55:59 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/ollama#77261