Please update gptel first -- errors are often fixed by the time they're reported.
Bug Description
When a Claude model via a LiteLLM proxy returns parallel tool calls in a streaming response, tool calls with missing/unparseable arguments end up with nil args. This crashes any tool function that uses its arguments (e.g. gptel-agent--task crashes at (capitalize agent-type) with Wrong type argument: char-or-string-p, nil).
Backend
OpenAI/Azure
Steps to Reproduce
- Configure gptel with an OpenAI-compatible backend pointing to a LiteLLM proxy serving Claude models, with
:stream t
- Use gptel-agent with a tool that has
:confirm t and multiple required arguments (e.g. the Agent tool)
- Send a prompt that causes the model to invoke two parallel tool calls
- Accept the tool calls — the second call has
nil for its args plist, crashing the tool function
Additional Context
Emacs version: 31 (macOS)
gptel version: 20260309.505
gptel-agent version: 20260308.2122
Backend: OpenAI-compatible (LiteLLM proxy → Claude us.anthropic.claude-sonnet-4-6), streaming enabled
Root cause: In gptel-openai.el line ~94-102, the streaming [DONE] handler's cl-loop silently returns nil for args when gptel--json-read-string fails to parse empty or malformed argument strings.
Validated fix: Change line 105 from when name to when (and name args) to skip tool calls with nil args:
(cl-loop
for tool-call in tool-use
for spec = (plist-get tool-call :function)
for name = (plist-get spec :name)
for args-str = (plist-get spec :arguments)
for args = (or (ignore-errors (gptel--json-read-string args-str))
(when (and args-str (not (string-empty-p args-str)))
(lwarn 'gptel :warning
"gptel: failed to parse tool call args for %s: %s"
name args-str)
nil))
when (and name args) ; skip entries missing name or args (streaming parse artifacts)
collect (list :id (plist-get tool-call :id) :name name :args args)
into call-specs
finally (plist-put info :tool-use call-specs))
This fix has been tested locally and works—tool calls with nil args are now skipped silently instead of crashing the tool function.
Backtrace
Debugger entered--Lisp error: (wrong-type-argument char-or-string-p nil)
capitalize(nil)
#f(compiled-function () #<bytecode 0xea3893d3fc4a87b>)()
funcall(#f(compiled-function () #<bytecode 0xea3893d3fc4a87b>))
gptel-agent--task(#f(compiled-function (&rest args2) #<bytecode 0x1e113b6aa6de843b>) nil nil nil)
apply(gptel-agent--task #f(compiled-function (&rest args2) #<bytecode 0x1e113b6aa6de843b>) (nil nil nil))
gptel--accept-tool-calls(((#s(gptel-tool :function gptel-agent--task :name "Agent" ...) (:subagent_type "introspector" :description "Investigate Emacs errors" :prompt "...") #f(...))
(#s(gptel-tool :function gptel-agent--task :name "Agent" ...) nil #f(...))))
gptel--inspect-accept-tool-calls()
call-interactively(gptel--inspect-accept-tool-calls nil nil)
command-execute(gptel--inspect-accept-tool-calls)
Note: the second tool call in the list has `nil` as its args plist (should be a plist like the first call).
Log Information
Please update gptel first -- errors are often fixed by the time they're reported.
Bug Description
When a Claude model via a LiteLLM proxy returns parallel tool calls in a streaming response, tool calls with missing/unparseable arguments end up with
nilargs. This crashes any tool function that uses its arguments (e.g.gptel-agent--taskcrashes at(capitalize agent-type)withWrong type argument: char-or-string-p, nil).Backend
OpenAI/Azure
Steps to Reproduce
:stream t:confirm tand multiple required arguments (e.g. theAgenttool)nilfor its args plist, crashing the tool functionAdditional Context
Emacs version: 31 (macOS)
gptel version: 20260309.505
gptel-agent version: 20260308.2122
Backend: OpenAI-compatible (LiteLLM proxy → Claude us.anthropic.claude-sonnet-4-6), streaming enabled
Root cause: In
gptel-openai.elline ~94-102, the streaming[DONE]handler'scl-loopsilently returnsnilfor args whengptel--json-read-stringfails to parse empty or malformed argument strings.Validated fix: Change line 105 from
when nametowhen (and name args)to skip tool calls with nil args:This fix has been tested locally and works—tool calls with nil args are now skipped silently instead of crashing the tool function.
Backtrace
Log Information