Skip to content

MiniMax-M3 emits answer tokens before closing </think> — answer truncated after stripping reasoning #28

Description

@nelsonbarrac

Summary

On the hosted OpenAI-compatible API (https://api.minimax.io/v1/chat/completions), MiniMax-M3 with thinking enabled intermittently emits the first tokens of the final answer before closing the </think> block. As a result, once the <think>...</think> block is stripped, the user-facing answer starts mid-sentence (its opening words are lost inside the reasoning block).

This is reproducible directly against the API, with no client framework involved, in both streaming and non-streaming modes. It is a property of the raw generation, not of any downstream parser.

Environment

  • Model: MiniMax-M3
  • Endpoint: https://api.minimax.io/v1/chat/completions (OpenAI-compatible)
  • Thinking: enabled (default / adaptive)
  • Reproduced with raw curl/fetch — no SDK, no LangChain, no vLLM.

Reproduction

curl -s https://api.minimax.io/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $MINIMAX_API_KEY" \
  -d '{
    "model": "MiniMax-M3",
    "messages": [{ "role": "user", "content": "Hola" }],
    "stream": false
  }'

Run it ~8 times. In roughly 25% of runs the returned content looks like:

<think>
...reasoning... I should respond in a friendly manner.¡Hola! 👋 ¿Cómo
</think>

estás? Soy un asistente de IA aquí para ayudarte. ¿En qué puedo ayudarte hoy?

Note that the greeting ¡Hola! 👋 ¿Cómo was emitted inside the <think> block, and the text after </think> starts mid-sentence with estás?.

Actual behavior

The closing </think> boundary is placed after the model has already started the final answer, so the answer's opening tokens are trapped inside the reasoning block. Stripping <think>...</think> (the documented handling for the OpenAI native format) yields a truncated answer.

Observed rate on the prompt "Hola", non-streaming: 2/8 hard truncations + 1 partial (missing the leading ¡).

Expected behavior

</think> should close before any final-answer token is emitted. Everything inside <think>...</think> should be reasoning only; the final answer should be fully contained in the post-</think> content.

reasoning_split=true does not fix it (and is worse)

Setting reasoning_split=true (so thinking is returned in reasoning_content / reasoning_details) exhibits the same boundary defect: the answer's opening tokens land in reasoning_content, and content starts mid-sentence. Reproduced non-streaming as well:

content:           "? Soy un asistente de IA y estoy aquí para ayudarte..."
reasoning_content: "...I should respond in a friendly manner...¡Hola! 👋 ¿Cómo estás"

Impact

Any integration that separates reasoning from the answer (the documented pattern) shows user-facing responses that begin mid-sentence. It affects real replies, not just greetings.

Notes

  • M2.7 did not exhibit this in our testing.
  • Related but distinct reports (parser leaking <mm:think> tags): vLLM #45687, #46042; Kilo-Org/kilocode #11203. This report is about the raw hosted-API generation placing the </think> boundary a few tokens into the answer.

Metadata

Metadata

Assignees

No one assigned

    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