Skip to content

agent: Skip empty assistant messages for Mistral provider#47579

Merged
benbrandt merged 1 commit intozed-industries:mainfrom
ian-h-chamberlain:fix/mistral-assistant-400
Feb 13, 2026
Merged

agent: Skip empty assistant messages for Mistral provider#47579
benbrandt merged 1 commit intozed-industries:mainfrom
ian-h-chamberlain:fix/mistral-assistant-400

Conversation

@ian-h-chamberlain
Copy link
Contributor

@ian-h-chamberlain ian-h-chamberlain commented Jan 25, 2026

This small change may help with #39211, #35025 or #39031 although I'm not positive it will fix it entirely. At a minimum, it should prevent sending invalid requests to the Mistral API, which return a 400 error and can prevent the thread from progressing if it gets stuck in a retry loop.

This should prevent sending a message like { "role": "assistant", "content": "" } if for some reason the thread contains a message with an empty text content and no tool calls.

Some users (including myself) have encountered this with the Devstral 2 models, although it doesn't seem trivial to reproduce: #37021 (comment)

When it occurs, error logs look something like this:

2026-01-24T19:53:35-08:00 ERROR [crates/agent/src/thread.rs:984] invalid type: string "Failed to connect to Mistral API: 400 Bad Request {\"object\":\"error\",\"message\":\"Assistant message must have either content or tool_calls, but not none.\",\"type\":\"invalid_request_assistant_message\",\"param\":null,\"code\":\"3240\"}", expected struct EditFileToolOutput
2026-01-24T19:53:35-08:00 ERROR [crates/agent/src/thread.rs:984] invalid type: string "Failed to connect to Mistral API: 400 Bad Request {\"object\":\"error\",\"message\":\"Assistant message must have either content or tool_calls, but not none.\",\"type\":\"invalid_request_assistant_message\",\"param\":null,\"code\":\"3240\"}", expected struct EditFileToolOutput
2026-01-24T19:53:35-08:00 ERROR [crates/agent/src/thread.rs:984] invalid type: string "Failed to connect to Mistral API: 400 Bad Request {\"object\":\"error\",\"message\":\"Assistant message must have either content or tool_calls, but not none.\",\"type\":\"invalid_request_assistant_message\",\"param\":null,\"code\":\"3240\"}", expected struct EditFileToolOutput

Release Notes:

  • Fixed agent sometimes sending invalid messages to Mistral API

@cla-bot cla-bot bot added the cla-signed The user has signed the Contributor License Agreement label Jan 25, 2026
@SomeoneToIgnore SomeoneToIgnore added the area:ai Improvement related to Agent Panel, Edit Prediction, Copilot, or other AI features label Jan 25, 2026
@vianney
Copy link
Contributor

vianney commented Feb 6, 2026

I can confirm that this PR does help with the Mistral API.

The issue appears mostly when the agent calls the edit_file tool without any explanation before, e.g., when editing two files one after the other. It seems closely related to the way the edit_file tool works: when the model answers with such a tool call, Zed makes its next request by appending the model's answer without tool call in an "agent" block, followed by a "user" block asking to provide the content. If the model's answer consisted of only the tool call, we get an empty "agent" block, which is forbidden by the Mistral API.

Note however that this patch does not fix file editing completely for Mistral models. Sometimes, the Mistral model would answer to the content request with the file content correctly enclosed with backticks, but with some extra text appended afterwards. Zed happily writes the additional text to the file instead of showing it in the agent panel. As far as I can tell, this is an unrelated bug though.

@ian-h-chamberlain
Copy link
Contributor Author

Note however that this patch does not fix file editing completely for Mistral models. Sometimes, the Mistral model would answer to the content request with the file content correctly enclosed with backticks, but with some extra text appended afterwards. Zed happily writes the additional text to the file instead of showing it in the agent panel. As far as I can tell, this is an unrelated bug though.

Yes, I've noticed this too! Perhaps some tweaks to the tool description (or switching to DiffFenced edit format like the Google provider) would help with that that issue, but I didn't want to overload this PR.

The issue fixed here is a more deterministic fix in that it filters out requests which will definitely be considered invalid, but the diff format is fuzzier and probably deserves some eval testing to see if it really helps (although from what I can tell the eval tests don't include all providers by default).

@vianney
Copy link
Contributor

vianney commented Feb 9, 2026

Yes, I've noticed this too! Perhaps some tweaks to the tool description (or switching to DiffFenced edit format like the Google provider) would help with that that issue, but I didn't want to overload this PR.

DiffFenced would definitely make sense. Mistral Vibe uses fences, so I guess the models have been trained with it.

I have had quite some success too by enabling the streaming edit_file tool, even though the Mistral API is not streaming the tool call, so the whole edit appears at once.

The issue fixed here is a more deterministic fix in that it filters out requests which will definitely be considered invalid

My opinion probably doesn't matter much, but I totally agree that this patch is worth merging.

Copy link
Member

@benbrandt benbrandt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks!

@benbrandt benbrandt self-assigned this Feb 12, 2026
@benbrandt benbrandt enabled auto-merge (squash) February 12, 2026 12:55
@zed-industries-bot
Copy link
Contributor

zed-industries-bot commented Feb 12, 2026

Messages
📖

This PR includes links to the following GitHub Issues: #37021
If this PR aims to close an issue, please include a Closes #ISSUE line at the top of the PR body.

Generated by 🚫 dangerJS against 4429afd

This *may* help with zed-industries#39211 or zed-industries#39031 although I'm not positive. Ata
minimum, it should prevent sending invalid requests to the Mistral API,
which return a 400 error and prevent the thread from progressing.
auto-merge was automatically disabled February 13, 2026 03:19

Head branch was pushed to by a user without write access

@ian-h-chamberlain ian-h-chamberlain force-pushed the fix/mistral-assistant-400 branch from 9deb94a to 4429afd Compare February 13, 2026 03:19
@ian-h-chamberlain
Copy link
Contributor Author

Looks like CI failed trying to find the git merge-base since it only fetches with --depth 350 (guessing my branch was too far out of date).

Pushed a rebase, hopefully good to go for a CI run this time!

@benbrandt benbrandt enabled auto-merge (squash) February 13, 2026 11:43
@benbrandt benbrandt merged commit 49dee40 into zed-industries:main Feb 13, 2026
27 checks passed
@ian-h-chamberlain ian-h-chamberlain deleted the fix/mistral-assistant-400 branch February 13, 2026 15:55
@keizerkarel1
Copy link

keizerkarel1 commented Feb 19, 2026

I had this issue occasionally and switched models when it happened. Now it happens 100% of the time I ask it to edit files.

I am on Zed 0.224.6 where this fix should be merged.

chat md mistral.md
I'm not sure if I can get the actual toolcalls/errors from a log, so I exported the chat where I asked mistral to create files.

I set the profile to write and verified all tool calls are there. I allowed all of them explicitly and changed the default to allow, just in case.
settings.json

@vianney
Copy link
Contributor

vianney commented Feb 20, 2026

@keizerkarel1 This PR was merged in the 0.225.0 preview release. It is not included in 0.224.6.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:ai Improvement related to Agent Panel, Edit Prediction, Copilot, or other AI features cla-signed The user has signed the Contributor License Agreement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants