Skip to content

Devstral via LiteLLM OpenAI-compatible fails with invalid_request_message_order on first file edit #6346

Description

@MaximilianHess

Description

When OpenCode is configured to use Devstral (devstral-2512) through the OpenAI-compatible provider path (LiteLLM OpenAI-compatible endpoint), the run fails as soon as the agent performs an edit operation (i.e., when it tries to edit a file and then continue). The failure occurs immediately at the point where OpenCode attempts to proceed after the edit.

Error message:

litellm.BadRequestError: MistralException - {"object":"error","message":"Expected last role User or Tool (or Assistant with prefix True) for serving but got assistant","type":"invalid_request_message_order","param":null,"code":"3230"}. Received Model Group=devstral-2512 Available Model Group Fallbacks=None

The same workflow does not fail when Devstral is used through the native Mistral provider path (mistral_v1).

Our config:

{
  "$schema": "https://opencode.ai/config.json",

  "tools": {
    "bash": true,
    "edit": true,
    "write": true,
    "read": true,
    "grep": true,
    "glob": true,
    "list": true,
    "lsp": true,
    "patch": true,
    "skill": true,
    "todowrite": true,
    "todoread": true,
    "webfetch": true

  },

  "provider": {
    "ascii-mistral": {
      "npm": "@ai-sdk/mistral",
      "name": "ASCII LiteLLM (Mistral native)",
      "options": {
        "baseURL": "https://llm.ascii.ac.at/mistral/v1",
        "apiKey": "{env:ASCII_AGENTIC_CODING_KEY}"
      },
      "models": {
        "devstral-2512": {
          "name": "devstral-2512 (via LiteLLM)",
          "limit": { "context": 256000, "output": 256000 },
          "tool_call": true,
        },
        "codestral-2508": {
          "name": "codestral-2508 (via LiteLLM)",
          "limit": { "context": 128000, "output": 128000 },
          "tool_call": true,
        },
      }
    },
    "ascii-oai-compatible": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "ASCII LiteLLM",
      "options": {
        "baseURL": "https://llm.ascii.ac.at/v1",
        "apiKey": "{env:ASCII_AGENTIC_CODING_KEY}"
      },
      "models": {
        "devstral-2512": {
          "name": "devstral-2512 (via LiteLLM)",
          "limit": { "context": 256000, "output": 256000 },
          "tool_call": true,
        },
        "codestral-2508": {
          "name": "codestral-2508 (via LiteLLM)",
          "limit": { "context": 128000, "output": 128000 },
          "tool_call": true,
        },
      }
    }
  },

  "model": "ascii-oai-compatible/devstral-2512"
}

Is this likely a opencode or litellm issue?

OpenCode version

1.0.207

Steps to reproduce

No response

Screenshot and/or share link

No response

Operating System

No response

Terminal

No response

Activity

  1. github-actions commented on Dec 29, 2025

    @github-actions
    Contributor

    This issue might be related to existing LiteLLM and OpenAI-compatible provider issues. Please check:

    These issues all involve LiteLLM proxies or OpenAI-compatible providers and may provide context for troubleshooting.

    Feel free to ignore if your specific case with Devstral's message ordering is a distinct issue.

  2. maxious commented on Jan 6, 2026

    @maxious
    Contributor

    I had the same issue with vllm; mistral_common.exceptions.InvalidMessageStructureException: Unexpected role 'user' after role 'tool'

    The workaround from #2440 is to ensure your model id has the string "mistral" in it; devstral should probably be added too:

    if (model.providerID === "mistral" || model.api.id.toLowerCase().includes("mistral")) {

  3. eleqtrizit commented on Jan 18, 2026

    @eleqtrizit

    @MaximilianHess there is a config to ensure alternating roles for litellm for Mistral based models

    litellm_settings:
      request_timeout: 300
      drop_params: true
      set_verbose: true
      modify_params: true
      default_litellm_params:
        ensure_alternating_roles: true
        user_continue_message:
          role: user
          content: Please continue.
        assistant_continue_message:
          role: assistant
          content: Please continue.
    
  4. eleqtrizit commented on Jan 18, 2026

    @eleqtrizit

    One more thing, I don't know how you'r running vLLM, but only the nightlies support tool calling for OpenCode due to another bug with streaming tool calls, which is what OpenCode makes.

  5. geoHeil commented on Jan 19, 2026

    @geoHeil

    Works for me!

  6. LucasScellos commented on Jan 26, 2026

    @LucasScellos

    Hello @MaximilianHess
    This issue is resolved in OpenCode v1.1.36 and does not require any changes to your LiteLLM.
    The failure was caused by a message ordering mismatch between OpenCode and Mistral-based models leading to invalid sequences after tool calls.
    In my case, upgrading OpenCode fixes the problem by relaxing validation after tools calls

  7. montvid commented on Mar 5, 2026

    @montvid

    @MaximilianHess there is a config to ensure alternating roles for litellm for Mistral based models

    litellm_settings:
      request_timeout: 300
      drop_params: true
      set_verbose: true
      modify_params: true
      default_litellm_params:
        ensure_alternating_roles: true
        user_continue_message:
          role: user
          content: Please continue.
        assistant_continue_message:
          role: assistant
          content: Please continue.
    

    Using this workaround serving with vllm devstral 2. Mistral Vibe and Openclaw seem to crash without it. That and one needs to modify litellm/litellm_core_utils/prompt_templates/common_utils.py...

  8. vincentkelleher commented on Mar 23, 2026

    @vincentkelleher

    Renaming my Devstral2 model from devstral-medium-2512 to mistral-devstral-medium-2512 seems to work after reading #6346 (comment) 👍

    Adding Devstral to the Mistral prefixes could maybe help this issue ?

  9. removed
    bugSomething isn't working
    on May 3, 2026
  10. github-actions commented on Jul 3, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.

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

Metadata

Metadata

Assignees

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