Problem/Motivation
Streaming chat responses fail with:
Cannot rewind a generator that was already run in MistralChatMessageIterator->doIterate()
Root Cause
MistralChatMessageIterator::doIterate() iterates directly over $this->iterator, which is a raw PHP Generator from the Partitech SDK's SSEClient::getStream(). PHP Generators are
single-pass — they cannot be rewound.
The AI module pipeline re-iterates the stream in two places:
1. PromptJsonDecoder::decodeStreamingMessage() — iterates chunks to test for JSON (line 61), then wraps in ReplayedChatMessageIterator (line 93)
2. ReplayedChatMessageIterator::getIterator() — calls $this->iterator->getIterator() (line 20), which triggers a new doIterate() against the already-consumed Generator
In OpenAI, on the other hand, doIterate() calls $this->iterator->getIterator() — the OpenAI PHP SDK returns an IteratorAggregate that produces fresh iterators. The Partitech Mistral SDK returns a raw Generator.
Steps to reproduce
- Enable ai_provider_mistral and ai_chatbot
- Configure Mistral as default chat provider
- configure a block with a NON-agent assistant, enable streaming, place the block e.g. under content
- Send a chat message
- Observe: Cannot rewind a generator that was already run
Proposed resolution
Replace foreach in doIterate() with manual valid()/current()/next() iteration. foreach implicitly calls rewind() on the iterator before starting, which crashes on an already-started Generator. Manual iteration avoids rewind() entirely, so re-entering doIterate() continues from the current position.
Remaining tasks
User interface changes
API changes
Data model changes
Issue fork ai_provider_mistral-3572398
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
petar_basic commentedComment #4
petar_basic commentedApplied the fix — replaced foreach with manual valid()/current()/next() iteration in doIterate(). foreach calls rewind() implicitly which crashes on the Partitech SDK's Generator.
Tested with both single and double iteration via drush:
Double iteration (the actual bug scenario — PromptJsonDecoder peeks then ReplayedChatMessageIterator re-iterates):
Also tested via AI Explorers, and AI chatbot (non-agent assistant needed for streaming option to show up).
Note that I needed to apply fix from https://www.drupal.org/project/ai/issues/3571925 to make the streaming work in chat and in explorers.
Comment #5
petar_basic commentedComment #8
fago