Assistant returns empty string on thread

I’ve been using the assistants api from openai v 5.20.1 in Node JS to run threads in stream mode with the file_search and code_interpreter tools. The stream should return with a typed response format defined with zod.

this.client = new OpenAI({ apiKey });
// Create the assistant
const assistant = await this.client.beta.assistants.create({
    model: 'gpt-4o-mini',
    name: `Assistant Projet - ${project.name}`,
    instructions: await this.buildAssistantInstructions(project),
    tools: [{ type: 'file_search' }, { type: 'code_interpreter' }],
});
// Trigger the run stream
const stream = this.client.beta.threads.runs.stream(threadId, {
    assistant_id: assistant.id,
    additional_messages: additionalMessages,
    stream: true,
    response_format: zodResponseFormat(AiResponseSDK, 'ai_response'),
});
// Get response from stream events
let rawJsonBuffer = '';
let lastDisplayed = '';
for await (const ev of stream) {
    this.logger.debug('Received stream event:', JSON.stringify(ev));
    switch (ev.event) {
        case 'thread.run.queued':
            yield { type: 'status', data: { status: 'queued', runId: ev.data.id } as IStatusData };
            break;
        case 'thread.run.in_progress':
            yield { type: 'status', data: { status: 'in_progress', runId: ev.data.id } as IStatusData };
            break;
        case 'thread.message.delta': {
            const deltaPart = ev.data.delta.content?.[0];
            if (deltaPart?.type === 'text' && deltaPart.text?.value) {
                const fragment = deltaPart.text.value;
                this.logger.debug(fragment);
                rawJsonBuffer += fragment;
                const current = this.tryExtractMessageToDisplay(rawJsonBuffer);
                if (current && current !== lastDisplayed) {
                    const newChunk = current.slice(lastDisplayed.length);
                    if (newChunk) {
                        yield {
                            type: 'chunk',
                            data: {
                                chunk: newChunk,
                                accumulated: current,
                                rawDelta: fragment,
                            } as IChunkData,
                        };
                        lastDisplayed = current;
                    }
                }
            }
            break;
        }
        case 'thread.run.completed':
            yield { type: 'status', data: { status: 'completed', runId: ev.data.id } as IStatusData };
            break;
        case 'thread.run.failed':
        case 'thread.run.cancelled':
            yield {
                type: 'error',
                data: {
                    taskCompleted: false,
                    error: `Run ${ev.event.replace('thread.run.', '')}`,
                } as IErrorData,
            };
            return;
    }
}

It’s been working fine for some months, it reads files, it views images and generates files.
In a particular thread of an assistant, the assistant generated the first message, then after the first user message (a long message that contained two images) every run on the thread returns an empty string. The thread.message.delta event never occurs. I’ve noticed that in all runs the code_interpreter tool is being called, I have logs that show:

Received stream event:
{"event":"thread.run.step.delta","data":{"id":"step_id","object":"thread.run.step.delta","delta":{"step_details":{"type":"tool_calls","tool_calls":[{"index":0,"type":"code_interpreter","code_interpreter":{"input":" Li"}}]}}}}

When I disable the code_interpreter tool keep the file_search tool and retry, the logs change to this:

Received stream event:
{"event":"thread.run.step.created","data":{"id":"step_id","object":"thread.run.step","created_at":1773827461,"run_id":"run_id","assistant_id":"asst_id","thread_id":"thread_id","type":"tool_calls","status":"in_progress","cancelled_at":null,"completed_at":null,"expires_at":1773828052,"failed_at":null,"last_error":null,"step_details":{"type":"tool_calls","tool_calls":[]},"usage":null}}

But still responds with an empty message
Then I disable both the code_interpreter and the file_search tools, it works again, but I lose the tools.
The same configuration with the tools enabled works in other assistants that share instructions.