[PR #7490] fix(opencode): resolve Mistral tool→user message ordering error #12417

Open
opened 2026-02-16 18:17:19 -05:00 by yindo · 0 comments
Owner

Original Pull Request: https://github.com/anomalyco/opencode/pull/7490

State: open
Merged: No


Issue

Fixes #7488

Problem

When using Mistral or Devstral models with tool calls (especially via vLLM or openai-compatible endpoints), requests fail with:

  mistral_common.exceptions.InvalidMessageStructureException:
  Unexpected role 'user' after role 'tool'

I guess this occurs because Mistral enforces strict message ordering: a tool message must be followed by an assistant message before any user message.

I then looked in the code and saw the transform logic to fix message ordering already existed in transform.ts, but it never ran because the middleware in llm.ts line 187 was transforming the wrong parameter (args.params.prompt instead of args.params.messages) (im TS noob so please help me out here if wrong).

The changes I did:

  1. The middleware stuff in src/session/llm.ts: Changed transform to target args.params.messages instead of prompt
  2. Then included more model name variants (src/provider/transform.ts): Now detects Mistral variants including:
    • Devstral models
    • Models served via openai-compatible providers
    • Checks both model.id and model.api.id
  3. Up tests(test/provider/transform.test.ts): 6 new

The flow should now be from userassistant (tool_calls) → tooluser to userassistant (tool_calls) → toolassistant ("Done.") → user
I hope this meets your standards. :)

**Original Pull Request:** https://github.com/anomalyco/opencode/pull/7490 **State:** open **Merged:** No --- ## Issue Fixes #7488 ## Problem When using Mistral or Devstral models with tool calls (especially via vLLM or openai-compatible endpoints), requests fail with: ```bash mistral_common.exceptions.InvalidMessageStructureException: Unexpected role 'user' after role 'tool' ``` I guess this occurs because Mistral enforces strict message ordering: a tool message must be followed by an assistant message before any user message. I then looked in the code and saw the transform logic to fix message ordering already existed in `transform.ts`, but it never ran because the middleware in `llm.ts` line 187 was transforming the wrong parameter (`args.params.prompt` instead of `args.params.messages`) (im TS noob so please help me out here if wrong). The changes I did: 1. The middleware stuff in `src/session/llm.ts`: Changed transform to target `args.params.messages` instead of `prompt` 2. Then included more model name variants (`src/provider/transform.ts`): Now detects Mistral variants including: - Devstral models - Models served via openai-compatible providers - Checks both `model.id` and `model.api.id` 3. Up tests(`test/provider/transform.test.ts`): 6 new The flow should now be from `user` → `assistant` (tool_calls) → `tool` → `user` to `user` → `assistant` (tool_calls) → `tool` → `assistant` ("Done.") → `user` I hope this meets your standards. :)
yindo added the pull-request label 2026-02-16 18:17:19 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: anomalyco/opencode#12417