siyuan-note/siyuan · error
streamed function call is missing from the terminal response
Error message
streamed function call is missing from the terminal response
What it means
The adapter accumulates function_call deltas keyed by output index in stream.responseToolCalls. The terminal response's Output array must contain function_call items at exactly those indices. A streamed index with no terminal counterpart means the deltas and the final response disagree about which calls exist, so the adapter aborts rather than emit a tool call whose final state is unknown.
Source
Thrown at kernel/util/openai_completion.go:505
func (stream *OpenAICompletionStream) queueResponseTerminal(response openai.CreateResponseResponse) error {
if err := responseResultError(response); err != nil {
return err
}
terminalToolCalls := map[int]struct{}{}
for index, raw := range response.Output {
item, ok := responseOutputItem(raw)
if !ok || item.Type != "function_call" {
continue
}
if item.Status == "incomplete" || item.Status == "in_progress" ||
(response.Status == openai.ResponseStatusIncomplete && item.Status != "completed") {
return errors.New("response ended with an incomplete function call")
}
terminalToolCalls[index] = struct{}{}
}
for index := range stream.responseToolCalls {
if _, ok := terminalToolCalls[index]; !ok {
return errors.New("streamed function call is missing from the terminal response")
}
}
output, err := MarshalOpenAIResponseOutput(response.Output)
if err != nil {
return err
}
stream.responseOutput = output
for index, raw := range response.Output {
item, ok := responseOutputItem(raw)
if !ok || item.Type != "function_call" {
continue
}
current := stream.responseToolCalls[index]
if current.ID != "" && item.CallID != "" && current.ID != item.CallID {
return errors.New("streamed function call ID does not match the terminal response")
}
if current.Function.Name != "" && item.Name != "" && current.Function.Name != item.Name {View on GitHub (pinned to afa823b6b4)
Solutions
- Retry the request — assembly races are often transient on gateways.
- Reproduce against the official endpoint; if clean there, upgrade or replace the gateway.
- Use non-streaming requests (CreateOpenAICompletion) for tool-heavy conversations on that provider.
- Capture an SSE trace and report it to the gateway maintainers.
Example fix
// before: streaming tool calls through a flaky gateway
{"apiBase": "https://my-gateway/v1", "protocol": "openai-responses", "stream": true}
// after: same gateway, terminal output as the single source of truth
{"apiBase": "https://my-gateway/v1", "protocol": "openai-responses", "stream": false} Defensive patterns
Strategy: fallback
Try / catch
On mismatch errors, treat the whole stream as unusable — never execute tool calls assembled from deltas — and rerun the step non-streaming so the terminal output is the single source of truth.
Prevention
- Prefer fully compliant endpoints when tool calling matters
- Keep gateways current
- Retain SSE traces when certifying a new provider
- Design callers to rerun a step rather than salvage a partial stream
When it happens
Trigger: Providers that reorder or drop items between delta emission and final assembly; a message item inserted into the terminal output shifting indices; gateways merging or regenerating events from multiple upstream attempts.
Common situations: OpenAI-compatible gateways with index-handling bugs on parallel tool calls; mid-stream provider failover changing assembly behavior.
Related errors
- streamed function call ID does not match the terminal respon
- streamed function name does not match the terminal response
- streamed function arguments do not match the terminal respon
- streamed response text does not match the terminal response
- response stream ended before a terminal event
AI-assisted analysis of siyuan-note/siyuan@afa823b6b4 (2026-08-18).
Data as JSON: /api/errors/d042fdd162143cd4.
Report an issue: GitHub.