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:
- Receive tool call from LiteLLM
- Execute the weather skill
- 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:
- Non-standard fields: The model returns
reasoning_content and provider_specific_fields (Harmony template specific)
- Parser fragility: OpenClaw's parser may expect strict OpenAI schema and chokes on extra fields
- 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)
Requests
- Can OpenClaw provide more lenient JSON parsing that ignores extra fields not in the OpenAI spec?
- Can OpenClaw log the raw JSON it's trying to parse when this error occurs for easier debugging?
- Is there a way to force OpenClaw to use streaming mode for specific models?
- 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.
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
openai/gpt-oss-120bvia lmdeploy 0.12.0litellm/ga3/gpt-oss-120bWhat 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
OpenClaw skill request
Expected behavior
OpenClaw should:
Actual behavior
OpenClaw returns to Matrix chat:
Analysis
Working direct test (non-streaming)
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": trueResponse (works):
Key difference: Non-streaming includes
reasoning_contentandprovider_specific_fieldswhich streaming does not.Hypothesis
OpenClaw's JSON parser fails on GPT-OSS-120B responses because:
reasoning_contentandprovider_specific_fields(Harmony template specific)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)
drop_params: trueto LiteLLM config (fixes OpenWebUI but not OpenClaw)stream: trueat LiteLLM level (OpenClaw still fails)supports_function_calling: trueflagsRequests
Logs
lmdeploy logs (working)
Note:
reason "stop"instead ofreason "tool_calls"suggests OpenClaw may be receiving the response incorrectly.OpenClaw error (only visible in Matrix chat)
Additional context
The pattern suggests OpenClaw has a model-specific compatibility issue with responses containing extensions to the OpenAI schema, particularly in non-streaming mode.