Skip to content

[Bug]: GPT-OSS-120B function calling fails with JSON parse error in OpenClaw #9956

Description

@ga-it

GPT-OSS-120B function calling fails with JSON parse error in OpenClaw

Summary

When using openai/gpt-oss-120b (via lmdeploy) through LiteLLM proxy, OpenClaw consistently fails to parse tool call responses with error: Expected property name or '}' in JSON at position 2 (line 2 column 1). The same setup works perfectly in OpenWebUI, suggesting an OpenClaw-specific parsing issue.

Related Issues

Environment

  • OpenClaw version: OpenClaw 2026.2.4
  • Model: openai/gpt-oss-120b via lmdeploy 0.12.0
  • Inference backend: lmdeploy (turbomind, mxfp4 quantization)
  • Proxy: LiteLLM
  • Model config in OpenClaw: litellm/ga3/gpt-oss-120b

What works

✅ Direct API test to lmdeploy (returns proper tool calls)
✅ Direct API test to LiteLLM proxy (returns proper tool calls)
✅ OpenWebUI using same LiteLLM proxy (tool calls work)
✅ Streaming mode responses parse correctly

What fails

❌ OpenClaw → LiteLLM → lmdeploy (JSON parse error)
❌ Non-streaming responses specifically

Reproduction

LiteLLM model config

- model_name: "ga3/gpt-oss-120b"
  litellm_params:
    model: "openai/openai/gpt-oss-120b"
    api_base: http://lmdeploy.foo.bar:23333/v1
    api_key: xxx
    timeout: 240
    max_parallel_requests: 12
    rpm: 360
    tpm: 360000
    supports_function_calling: true
    supports_parallel_function_calling: true
    drop_params: true
    stream: true  # Even forcing this doesn't help
  model_info:
    mode: chat
    supports_reasoning: True
    supports_function_calling: true

OpenClaw skill request

User: What is my weather in Johannesburg South Africa today?

Expected behavior

OpenClaw should:

  1. Receive tool call from LiteLLM
  2. Execute the weather skill
  3. Return results to user

Actual behavior

OpenClaw returns to Matrix chat:

Expected property name or '}' in JSON at position 2 (line 2 column 1)

Analysis

Working direct test (non-streaming)

curl -X POST http://127.0.0.1:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer xxx" \
  -d '{
    "model": "ga3/gpt-oss-120b",
    "messages": [{"role": "user", "content": "What is the weather in London?"}],
    "tools": [{
      "type": "function",
      "function": {
        "name": "get_weather",
        "description": "Get current weather",
        "parameters": {"type": "object", "properties": {"location": {"type": "string"}}, "required": ["location"]}
      }
    }]
  }'

Response (works):

{
  "id": "4",
  "created": 1770320271,
  "model": "openai/gpt-oss-120b",
  "object": "chat.completion",
  "choices": [{
    "finish_reason": "tool_calls",
    "index": 0,
    "message": {
      "content": null,
      "role": "assistant",
      "tool_calls": [{
        "function": {
          "arguments": "{\n  \"location\": \"London\"\n}",
          "name": "get_weather"
        },
        "id": "chatcmpl-tool-gPtgXvCRuXw9qE6pjiNMdX",
        "type": "function"
      }],
      "reasoning_content": "User wants current weather in London. Use get_weather function.",
      "provider_specific_fields": {
        "reasoning_content": "User wants current weather in London. Use get_weather function."
      }
    }
  }],
  "usage": {"completion_tokens": 39, "prompt_tokens": 124, "total_tokens": 163}
}

Working streaming test

# Same curl but with "stream": true

Response (works):

data: {"id":"5","created":1770320863,"model":"openai/gpt-oss-120b","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"role":"assistant","tool_calls":[{"id":"chatcmpl-tool-zzzsJAtzfkhEWE2CwndTHw","function":{"arguments":"{\n  \"location\": \"London\"\n}","name":"get_weather"},"type":"function","index":0}]}}]}
data: {"id":"5","created":1770320863,"model":"openai/gpt-oss-120b","object":"chat.completion.chunk","choices":[{"finish_reason":"tool_calls","index":0,"delta":{}}]}
data: [DONE]

Key difference: Non-streaming includes reasoning_content and provider_specific_fields which streaming does not.

Hypothesis

OpenClaw's JSON parser fails on GPT-OSS-120B responses because:

  1. Non-standard fields: The model returns reasoning_content and provider_specific_fields (Harmony template specific)
  2. Parser fragility: OpenClaw's parser may expect strict OpenAI schema and chokes on extra fields
  3. Streaming vs non-streaming: Different code paths handle these differently - streaming works because it doesn't include these fields

Similar to issues reported in #9916 with other models, OpenClaw appears to have stricter JSON parsing in non-streaming mode that breaks with responses containing model-specific extensions.

Attempted workarounds (all failed)

  • Added drop_params: true to LiteLLM config (fixes OpenWebUI but not OpenClaw)
  • Forced stream: true at LiteLLM level (OpenClaw still fails)
  • Increased lmdeploy session length and cache settings
  • Added explicit supports_function_calling: true flags

Requests

  1. Can OpenClaw provide more lenient JSON parsing that ignores extra fields not in the OpenAI spec?
  2. Can OpenClaw log the raw JSON it's trying to parse when this error occurs for easier debugging?
  3. Is there a way to force OpenClaw to use streaming mode for specific models?
  4. Does OpenClaw strip non-OpenAI fields before parsing? If not, should it?

Logs

lmdeploy logs (working)

2026-02-05 21:07:34,610 - lmdeploy - INFO - logger.py:45 - session=Session(id=14, step=0), adapter_name=None, input_tokens=8053, gen_config=GenerationConfig(...)
2026-02-05 21:07:37,032 - lmdeploy - INFO - async_engine.py:498 - session 14 finished, reason "stop", input_tokens 8053, output_tokens 122

Note: reason "stop" instead of reason "tool_calls" suggests OpenClaw may be receiving the response incorrectly.

OpenClaw error (only visible in Matrix chat)

Expected property name or '}' in JSON at position 2 (line 2 column 1)

Additional context

  • This error occurs 100% of the time with gpt-oss-120b
  • Per issue reports, similar failures occur sometimes with kimi-k2
  • OpenWebUI handles the exact same responses without issue
  • Direct LiteLLM API calls work perfectly
  • The only difference is OpenClaw's request/response handling

The pattern suggests OpenClaw has a model-specific compatibility issue with responses containing extensions to the OpenAI schema, particularly in non-streaming mode.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingstaleMarked as stale due to inactivity

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions