Skip to content

ChatCompletionAccumulator.AddChunk panics when tool_call's index is not equal to slice index #464

@dujiajun

Description

@dujiajun

Problem

Hi team, I encountered a panic when using this SDK to handle my own model's response.

panic: runtime error: index out of range [-1]

goroutine 1 [running]:
github.com/openai/openai-go.(*ChatCompletion).accumulateDelta(_, {{0x1400014e1c7, 0x17}, {0x14000158008, 0x1, 0x1}, 0x688b2f81, {0x1400014e21f, 0x29}, {0x1400014e1ea, ...}, ...})
	/Users/du/go/pkg/mod/github.com/openai/[email protected]/streamaccumulator.go:129 +0xabc
github.com/openai/openai-go.(*ChatCompletionAccumulator).AddChunk(_, {{0x1400014e1c7, 0x17}, {0x14000158008, 0x1, 0x1}, 0x688b2f81, {0x1400014e21f, 0x29}, {0x1400014e1ea, ...}, ...})
	/Users/du/go/pkg/mod/github.com/openai/[email protected]/streamaccumulator.go:40 +0x64

Cause

After reviewing the source code, I found that accumulateDelta assumes the index value of the tool_call is equal to the index where the tool_call is present in the Go slice. This assumption seems to cause the panic when the index is out of order or negative (e.g., -1). It's unclear whether this is an issue with the SDK's implementation or if our model's response isn't compatible with OpenAI's expected format.

Here’s the relevant code snippet:

// func (cc *ChatCompletion) accumulateDelta(chunk ChatCompletionChunk) bool

for j := range delta.Delta.ToolCalls {
			deltaTool := &delta.Delta.ToolCalls[j]

			choice.Message.ToolCalls = expandToFit(choice.Message.ToolCalls, int(deltaTool.Index))
			tool := &choice.Message.ToolCalls[deltaTool.Index]

			if deltaTool.ID != "" {
				tool.ID = deltaTool.ID
			}
			if deltaTool.Type != "" {
				tool.Type = constant.Function(deltaTool.Type)
			}
			tool.Function.Name += deltaTool.Function.Name
			tool.Function.Arguments += deltaTool.Function.Arguments
		}

Reproduce

Here is a minimal example to reproduce the issue. In this example, the tool_calls includes a tool_call with an invalid index value of -1:

package main

import (
	"encoding/json"

	"github.com/openai/openai-go"
)

func main() {
	acc := openai.ChatCompletionAccumulator{}
	chunk := openai.ChatCompletionChunk{}
	str := "{\"id\":\"gen-1753952129163910909\",\"object\":\"chat.completion.chunk\",\"created\":1753952129,\"model\":\"model\",\"choices\":[{\"index\":0,\"delta\":{\"role\":null,\"content\":null,\"reasoning_content\":null,\"tool_calls\":[{\"id\":\"call_goVJu3KUQtuahQuqW6wgzQ\",\"index\":-1,\"type\":\"function\",\"function\":{\"name\":\"doc_search\",\"arguments\":\"\"}}]},\"logprobs\":null,\"finish_reason\":null,\"matched_stop\":null}],\"usage\":null}"
	err := json.Unmarshal([]byte(str), &chunk)
	if err != nil {
		println(err)
	}
	acc.AddChunk(chunk)
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions