AI_TypeValidationError: Type validation failed: Value: {"id":"chatcmpl-1790267014577",...,"choices":[{"index":0,"delta":{"tool_calls":[{"id":"call_c0c7387a74ec4150a6586e15","type":"function","function":{"name":"bash","arguments":{"command":"echo hello"}}}]},"finish_reason":"stop"}]}
Error message: [{"code":"invalid_union","errors":[[
{"expected":"string","code":"invalid_type","path":["choices",0,"delta","tool_calls",0,"function","arguments"],"message":"Invalid input: expected string, received object"}],[
{"expected":"object","code":"invalid_type","path":["error"],"message":"Invalid input: expected object, received undefined"}]],"path":[],"message":"Invalid input"}]
No error is logged by the g4f API itself — it streams the chunk as if it were valid.
Before submitting
☑️ I checked Known Issues
☑️ I searched existing issues — found #3373 (same malformed shape, closed after an Ollama-worker-only fix; bug persists via the Puter provider)
Configuration (Required)
z-ai:z-ai/glm-5.3(also reproduced:openrouter:~google/gemini-flash-latest,infron:google/gemini-3.8-flash:priority)Puterg4f api, OpenAI-compatible/v1/chat/completions)Bug description
Clear steps to reproduce:
delta.tool_calls[0].function.argumentsas a JSON object, the tool call has noindexfield, and the complete tool call plusfinish_reason:"stop"arrive in a single chunk:{"id":"chatcmpl-1790267014577","object":"chat.completion.chunk","created":1790267014, "model":"z-ai:z-ai/glm-5.3","choices":[{"index":0,"delta":{"tool_calls":[ {"id":"call_c0c7387a74ec4150a6586e15","type":"function", "function":{"name":"bash","arguments":{"command":"echo hello"}}}]}, "finish_reason":"stop"}]}function.argumentsas a JSON-encoded string ("arguments":"{\"command\":\"echo hello\"}"), per the OpenAI streaming schema. Strict clients (opencode via@ai-sdk/openai-compatible) reject the whole stream withAI_TypeValidationError: expected string, received object.Environment
ai-sdkto g4f Puter proxy (puter.g4f-dev.workers.dev)Screenshots/Logs
No error is logged by the g4f API itself — it streams the chunk as if it were valid.
Additional context
g4f/Provider/needs_auth/Puter.py(lines ~506–508) relays upstreamdelta.tool_callsverbatim —yield ToolCalls(choice["delta"]["tool_calls"])— without normalizingfunction.argumentsto a string (and without adding the streamingindexfield). g4f's own text-parsed tool path does this correctly vianormalize_tool_calls(g4f/tools/tool_support.py,json.dumps(args)), so only the native-relay path leaks the object form.