Skip to content

Tool call errors with Expected 'content' to be a string or an array #13471

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
anudit opened this issue May 12, 2025 · 2 comments · Fixed by #13477
Closed

Tool call errors with Expected 'content' to be a string or an array #13471

anudit opened this issue May 12, 2025 · 2 comments · Fixed by #13477
Labels
bug Something isn't working

Comments

@anudit
Copy link
Contributor

anudit commented May 12, 2025

Name and Version

version: 5350 (c104023)
built with Apple clang version 17.0.0 (clang-1700.0.13.3) for arm64-apple-darwin24.4.0

Operating systems

Mac

GGML backends

Metal

Hardware

M2 Max

Models

Tested with gemma-3-4b-it-qat and internvl3-8b-instruct

Problem description & steps to reproduce

Tool call errors with Expected 'content' to be a string or an array.

Mainly because llama.cpp server responds with "content": null, in the assistant tool call response, which when sent back to the server with tool call response errors.
If I change the "content": null, to "content": "", it works.

Repro:

import { generateText } from '@xsai/generate-text'
import { tool } from '@xsai/tool'
import * as v from 'valibot'

async function main() {

  const weather = await tool({
    description: 'Get the weather in a location',
    execute: ({ location }) => JSON.stringify({
      location,
      temperature: 42,
    }),
    name: 'weather',
    parameters: v.object({
      location: v.pipe(
        v.string(),
        v.description('The location to get the weather for'),
      ),
    }),
  })

  const { text } = await generateText({
    apiKey: "xx",
    baseURL: 'http://localhost:9001/v1/',
    maxSteps: 10,
    messages: [
      {
        content: 'You are a helpful assistant.',
        role: 'system',
      },
      {
        content: 'What is the weather in San Francisco?',
        role: 'user',
      },
    ],
    model: 'xx',
    tools: [weather],
  })

  console.log({text})
}

main()

Final Req (this errors),

{
  "messages": [
    {
      "content": "You are a helpful assistant.",
      "role": "system"
    },
    {
      "content": "What is the weather in San Francisco?",
      "role": "user"
    },
    {
      "role": "assistant",
      "content": null,
      "tool_calls": [
        {
          "type": "function",
          "function": {
            "name": "weather",
            "arguments": "{\"location\":\"San Francisco\"}"
          },
          "id": "IbcHFjCPI7tAwLeMoOlBhn9d5ZEqWY6W"
        }
      ]
    },
    {
      "content": "{\"location\":\"San Francisco\",\"temperature\":42}",
      "role": "tool",
      "tool_call_id": "IbcHFjCPI7tAwLeMoOlBhn9d5ZEqWY6W"
    }
  ],
  "model": "xx",
  "tools": [
    {
      "function": {
        "description": "Get the weather in a location",
        "name": "weather",
        "parameters": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "location": {
              "type": "string",
              "description": "The location to get the weather for"
            }
          },
          "required": [
            "location"
          ],
          "additionalProperties": false
        },
        "strict": true
      },
      "type": "function"
    }
  ],
  "stream": false
}
@CISC CISC added bug Something isn't working and removed bug-unconfirmed labels May 12, 2025
@CISC
Copy link
Collaborator

CISC commented May 12, 2025

The offending check is here:

if (content.is_string()) {
continue;
}
if (!content.is_array()) {
throw std::runtime_error("Expected 'content' to be a string or an array");
}

Since null content is valid it should be enough to add content.is_null() to the first check, but that might cause things to break elsewhere, can you test/add a PR?

@anudit
Copy link
Contributor Author

anudit commented May 12, 2025

@CISC Made a PR, works for me locally in our projects and tests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants