[BUG] malformed tool_reference content block injected into history breaks vLLM chat-template rendering (jinja2 TemplateError: "Unexpected item type in content")

Open 💬 0 comments Opened Jul 15, 2026 by marcorobiati

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

When a tool (e.g. WebFetch) is invoked without its full schema loaded, the initial call fails with InputValidationError, and the recovery path (calling ToolSearch with select:<ToolName>) returns a tool result containing a content block of the form:

{"type": "tool_reference", "tool_name": "WebFetch"}

This block type is not part of the documented Anthropic Messages content-block schema (text, image, tool_use, tool_result, document, thinking, redacted_thinking). Once this block is written into conversation history, it gets replayed in subsequent API calls. Any downstream consumer of that history that strictly validates/renders content blocks against the standard schema will reject it — observed concretely as a jinja2.exceptions.TemplateError: Unexpected item type in content when the conversation was replayed through a self-hosted OpenAI/Anthropic-compatible endpoint (vLLM + transformers.apply_chat_template).

What Should Happen?

no error.

Error Messages/Logs

"{
  "role": "user",
  "content": "Help me create an issue for the mantainer. Analyze https://github.com/open-gsd/gsd-core/blob/next/CONTRIBUTING.md e create me an issue of this problem respecting their contribution rules",
  "_tokens": 43
}"
"{
  "role": "assistant",
  "content": [
    {
      "type": "thinking",
      "thinking": "The user wants me to analyze the CONTRIBUTING.md file and create an issue about the \"Bash is not defined\" error in Workflow scripts. I need to first fetch and read the CONTRIBUTING.md file to understand their issue template and contribution guidelines.\n",
      "signature": "fda63472c0d345c79f517834a4cadeaf"
    },
    {
      "type": "tool_use",
      "id": "chatcmpl-tool-86344fd2554aad12",
      "name": "WebFetch",
      "input": {
        "url": "https://raw.githubusercontent.com/open-gsd/gsd-core/next/CONTRIBUTING.md"
      }
    }
  ],
  "_tokens": 130
}"
"{
  "role": "user",
  "content": [
    {
      "type": "tool_result",
      "content": "InputValidationError: WebFetch failed due to the following issue:\nThe required parameter prompt is missing\n\nThis tool's schema was not sent to the API — it was not in the discovered-tool set derived from message history. Without the schema in your prompt, typed parameters (arrays, numbers, booleans) get emitted as strings and the client-side parser rejects them. Load the tool first: call ToolSearch with query \"select:WebFetch\", then retry this call. For reference, this tool's input schema is: {\"$schema\":\"https://json-schema.org/draft/2020-12/schema\",\"type\":\"object\",\"properties\":{\"url\":{\"description\":\"The URL to fetch content from\",\"type\":\"string\",\"format\":\"uri\"},\"prompt\":{\"description\":\"The prompt to run on the fetched content\",\"type\":\"string\"}},\"required\":[\"url\",\"prompt\"],\"additionalProperties\":false}",
      "is_error": true,
      "tool_use_id": "chatcmpl-tool-86344fd2554aad12"
    }
  ],
  "_tokens": 228
}"
"{
  "role": "assistant",
  "content": [
    {
      "type": "thinking",
      "thinking": "The WebFetch tool requires both 'url' and 'prompt' parameters, so I need to add a minimal prompt to complete the request.\n",
      "signature": "7be44cfc06eb4070be23d2fdff3bbbf5"
    },
    {
      "type": "tool_use",
      "id": "chatcmpl-tool-988b385abf51fda0",
      "name": "ToolSearch",
      "input": {
        "max_results": 1,
        "query": "select:WebFetch"
      }
    }
  ],
  "_tokens": 102
}"
"{
  "role": "user",
  "content": [
    {
      "type": "tool_result",
      "tool_use_id": "chatcmpl-tool-988b385abf51fda0",
      "content": [
        {
          "type": "tool_reference",
          "tool_name": "WebFetch"
        }
      ]
    },
    {
      "type": "text",
      "text": "Tool loaded.\n"
    },
    {
      "type": "text",
      "text": "try again please",
      "cache_control": {
        "type": "ephemeral"
      }
    }
  ],
  "_tokens": 72
}"

Steps to Reproduce

  1. Configure Claude Code against an Anthropic-compatible endpoint (e.g. local vLLM).
  2. Trigger a tool call before its schema is fully loaded (observed with WebFetch missing the required prompt param).
  3. Observe the ToolSearch recovery flow inject a tool_reference block into the tool_result content array.
  4. Continue the conversation — the next request containing that history is rejected by the receiving server.

Claude Model

Other

Is this a regression?

Yes, this worked in a previous version

Last Working Version

_No response_

Claude Code Version

2.1.210

Platform

Other

Operating System

Ubuntu/Debian Linux

Terminal/Shell

Other

Additional Information

This may be intentional internal protocol shape for Anthropic-hosted inference, but it's undocumented and breaks non-Anthropic-hosted or self-hosted endpoints that validate against the public Messages API content-block schema. Worth documenting tool_reference as an official block type, or ensuring it's never written into replayable history sent to third-party-compatible endpoints.

View original on GitHub ↗