{"record":{"id":"fa1bf43a2858f411","repo":"siyuan-note/siyuan","slug":"streamed-function-name-does-not-match-the-terminal","errorCode":null,"errorMessage":"streamed function name does not match the terminal response","messagePattern":"streamed function name does not match the terminal response","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/util/openai_completion.go","lineNumber":524,"sourceCode":"\t\t}\n\t}\n\toutput, err := MarshalOpenAIResponseOutput(response.Output)\n\tif err != nil {\n\t\treturn err\n\t}\n\tstream.responseOutput = output\n\n\tfor index, raw := range response.Output {\n\t\titem, ok := responseOutputItem(raw)\n\t\tif !ok || item.Type != \"function_call\" {\n\t\t\tcontinue\n\t\t}\n\t\tcurrent := stream.responseToolCalls[index]\n\t\tif current.ID != \"\" && item.CallID != \"\" && current.ID != item.CallID {\n\t\t\treturn errors.New(\"streamed function call ID does not match the terminal response\")\n\t\t}\n\t\tif current.Function.Name != \"\" && item.Name != \"\" && current.Function.Name != item.Name {\n\t\t\treturn errors.New(\"streamed function name does not match the terminal response\")\n\t\t}\n\t\tif current.Function.Arguments != item.Arguments &&\n\t\t\t!strings.HasPrefix(item.Arguments, current.Function.Arguments) {\n\t\t\treturn errors.New(\"streamed function arguments do not match the terminal response\")\n\t\t}\n\t\tdelta := openai.ToolCall{Type: openai.ToolTypeFunction}\n\t\tdeltaIndex := index\n\t\tdelta.Index = &deltaIndex\n\t\tchanged := false\n\t\tif current.ID == \"\" && item.CallID != \"\" {\n\t\t\tdelta.ID = item.CallID\n\t\t\tchanged = true\n\t\t}\n\t\tif current.Function.Name == \"\" && item.Name != \"\" {\n\t\t\tdelta.Function.Name = item.Name\n\t\t\tchanged = true\n\t\t}\n\t\tif current.Function.Arguments != item.Arguments && strings.HasPrefix(item.Arguments, current.Function.Arguments) {","sourceCodeStart":506,"sourceCodeEnd":542,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/afa823b6b4e4f183511e0bc0a3be93caa94c7c97/kernel/util/openai_completion.go#L506-L542","documentation":"The adapter compares the function name accumulated from stream deltas (current.Function.Name) with the terminal item.Name whenever both are non-empty. A mismatch means the streamed deltas and the final response disagree about which function to call, so dispatching on either value alone is unsafe and the stream fails.","triggerScenarios":"Gateways that rename or alias functions between streaming and finalization; parallel calls with server-side index swaps pairing the wrong name with accumulated state; event middleware rewriting function names.","commonSituations":"OpenAI-compatible gateways with tool-name normalization; mid-stream failover to a backend with a different tool schema.","solutions":["Retry the request once — transient inconsistencies often clear.","Reproduce against the official OpenAI endpoint; if clean there, upgrade or replace the gateway.","Disable streaming for tool calls on the affected provider.","Capture an SSE trace and report the name divergence."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"Drop the partial stream state and re-issue the request; if the same function name keeps diverging, route that provider's tool calls through non-streaming requests.","preventionTips":["Verify gateway tool-schema handling before enabling streaming tools","Keep gateway and SDK versions aligned","Alert on repeated stream-versus-terminal mismatches"],"tags":["streaming","tool-calls","openai","responses-api","name-mismatch"],"backgroundTag":"stream-state-mismatch","analyzedSha":"afa823b6b4e4f183511e0bc0a3be93caa94c7c97","analyzedAt":"2026-08-18T17:04:10.865Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}