Which inference path did you use?
MiniMax API
Inference parameters
API defaults (no temperature / top_p / top_k set). Also reproduced with temperature=0 - see Additional context.
Prompt / input
Endpoint: POST https://api.minimax.io/v1/chat/completions
tool_choice: {"type": "function", "function": {"name": "final_result"}}
Tool parameters schema:
{"type":"object","properties":{"groups":{"type":"array","items":{"type":"object","properties":{"item_ids":{"type":"array","items":{"type":"string"}}},"required":["item_ids"]}}},"required":["groups"]}
User message:
Sort the following items into groups, where each group contains items that belong to the same category:
id a1: apple
id a2: banana
id b1: carrot
id b2: potato
id c1: hammer
id c2: screwdriver
Explain which items belong together and why, then return the grouping.
Expected behavior
Three groups (fruit / vegetables / tools), all six ids present:
{"groups":[{"item_ids":["a1","a2"]},{"item_ids":["b1","b2"]},{"item_ids":["c1","c2"]}]}
Actual behavior
Roughly 15–35% of calls return only the first entry inside the array and flatten the rest into an invented top-level key item that does not exist in the schema.
The middle group is lost entirely — only 4 of the 6 ids survive:
{"groups":[{"item_ids":["a1","a2"]}],"item":{"item_ids":["c1","c2"]}}
The malformed output is byte-identical across independent failing calls.
There is no error signal. The response is a normal 200 OK with finish_reason: "tool_calls", syntactically valid JSON, and base_resp: {"status_code": 0}. Token counts look normal (nothing truncated). Because the surviving JSON is well-formed, standard clients that ignore unexpected keys (e.g. pydantic's default extra="ignore") drop the item key silently - so entries vanish with no exception and no retry.
The visible <think> block shows the model reasoning out the correct three groups in prose, then emitting the malformed structure anyway.
Additional context
Frequency: 7/20 (35%) on chat completions in the sharpest run; 10–35% across runs. Failures cluster — within a batch of concurrent requests it is often all-or-nothing rather than an even split, which may point to serving-side batching or routing correlating outcomes across simultaneous requests.
Not transport. Same signature on all three endpoints (N=20 each):
| Endpoint |
Violations |
/v1/chat/completions |
4/20 |
/v1/responses |
2/20 |
/anthropic/v1/messages |
3/20 |
Not sampling. temperature: 0 does not suppress it — 6/20 at temp 0 vs 3/20 at default, interleaved in a single batch so both arms share the same serving window.
Worse variant. Give the array element two fields and groups stops being an array at all, with both inner field names leaking to the top level:
{"groups":{"item":{"item_ids":["a1","a2"]},"category":"Fruits"},"item":{"item_ids":["c1","c2"]},"category":"Tools"}
Questions: Is this known / is a fix planned? Is there a supported strict or constrained-decoding mode for tool calls?
Update 2026-07-28: I re-tested this with a controlled experiment and the original diagnosis was too broad. It is not array-of-objects in general. Two conditions have to hold together:
- an element property named
item_ids (or similar item* name), and
- a prompt that never uses the word "item".
2×2 factorial, three independent serving windows, ~176 calls, requests throttled to 4 concurrent and all four cells interleaved so they share a window:
| element property |
prompt uses "item" |
prompt avoids "item" |
item_ids |
0/45 |
12/45 (27%) — per round 3/15, 4/15, 5/15 |
member_ids |
0/42 |
0/44 |
The whole effect is confined to one cell, so this is an interaction - neither factor does anything on its own. Two independent fixes each take it to zero:
- rename the property -
member_ids or element_ids is clean (0/86 across both prompts), same schema shape otherwise;
- or ground the name in the prompt - keeping
item_ids but ending the prompt with "Each group must list the id strings of its items." gives 0/45.
Only the second sentence differs between the two prompt arms:
prompt A (clean): Sort the following items into groups ... Explain which items
belong together and why, then return the grouping.
Each group must list the id strings of its items.
prompt B (27% bad): Sort the following products into groups ... Explain which
products belong together and why, then return the grouping.
Each group must list the id strings of its members.
Everything else - the schema, the six ids, tool_choice forcing the call - is unchanged from the original report. The malformed output is also unchanged: one group inside groups, one moved to a top-level item, the middle group gone. Every invented key I have observed, in every run, is literally item.
Guess at the mechanism, since it might point somewhere useful: items is the JSON Schema keyword that describes array elements. A property with that name and no anchor in the prompt looks like it gets conflated with the keyword, so the model emits a sibling item holding a single element instead of appending it to the array.
Realistic schemas with no item* property have been clean in everything I have run since — 26/26 calls on one real workload, and 56/56 on a larger schema across three different ways of encoding its numeric vectors (arrays, flattened scalars, delimited strings, all 0 violations). So restructuring a schema does not help; renaming the colliding property does.
This is no longer a problem for us, since we can easily work around it. I would love to hear what the cause/mechanism of this bug is though - I'm really curious.
Which inference path did you use?
MiniMax API
Inference parameters
API defaults (no temperature / top_p / top_k set). Also reproduced with temperature=0 - see Additional context.
Prompt / input
Expected behavior
Three groups (fruit / vegetables / tools), all six ids present:
{"groups":[{"item_ids":["a1","a2"]},{"item_ids":["b1","b2"]},{"item_ids":["c1","c2"]}]}Actual behavior
Roughly 15–35% of calls return only the first entry inside the array and flatten the rest into an invented top-level key
itemthat does not exist in the schema.The middle group is lost entirely — only 4 of the 6 ids survive:
{"groups":[{"item_ids":["a1","a2"]}],"item":{"item_ids":["c1","c2"]}}The malformed output is byte-identical across independent failing calls.
There is no error signal. The response is a normal
200 OKwithfinish_reason: "tool_calls", syntactically valid JSON, andbase_resp: {"status_code": 0}. Token counts look normal (nothing truncated). Because the surviving JSON is well-formed, standard clients that ignore unexpected keys (e.g. pydantic's defaultextra="ignore") drop theitemkey silently - so entries vanish with no exception and no retry.The visible
<think>block shows the model reasoning out the correct three groups in prose, then emitting the malformed structure anyway.Additional context
Frequency: 7/20 (35%) on chat completions in the sharpest run; 10–35% across runs. Failures cluster — within a batch of concurrent requests it is often all-or-nothing rather than an even split, which may point to serving-side batching or routing correlating outcomes across simultaneous requests.
Not transport. Same signature on all three endpoints (N=20 each):
/v1/chat/completions/v1/responses/anthropic/v1/messagesNot sampling.
temperature: 0does not suppress it — 6/20 at temp 0 vs 3/20 at default, interleaved in a single batch so both arms share the same serving window.Worse variant. Give the array element two fields and
groupsstops being an array at all, with both inner field names leaking to the top level:{"groups":{"item":{"item_ids":["a1","a2"]},"category":"Fruits"},"item":{"item_ids":["c1","c2"]},"category":"Tools"}Questions: Is this known / is a fix planned? Is there a supported strict or constrained-decoding mode for tool calls?
Update 2026-07-28: I re-tested this with a controlled experiment and the original diagnosis was too broad. It is not array-of-objects in general. Two conditions have to hold together:
item_ids(or similaritem*name), and2×2 factorial, three independent serving windows, ~176 calls, requests throttled to 4 concurrent and all four cells interleaved so they share a window:
item_idsmember_idsThe whole effect is confined to one cell, so this is an interaction - neither factor does anything on its own. Two independent fixes each take it to zero:
member_idsorelement_idsis clean (0/86 across both prompts), same schema shape otherwise;item_idsbut ending the prompt with "Each group must list the id strings of its items." gives 0/45.Only the second sentence differs between the two prompt arms:
Everything else - the schema, the six ids,
tool_choiceforcing the call - is unchanged from the original report. The malformed output is also unchanged: one group insidegroups, one moved to a top-levelitem, the middle group gone. Every invented key I have observed, in every run, is literallyitem.Guess at the mechanism, since it might point somewhere useful:
itemsis the JSON Schema keyword that describes array elements. A property with that name and no anchor in the prompt looks like it gets conflated with the keyword, so the model emits a siblingitemholding a single element instead of appending it to the array.Realistic schemas with no
item*property have been clean in everything I have run since — 26/26 calls on one real workload, and 56/56 on a larger schema across three different ways of encoding its numeric vectors (arrays, flattened scalars, delimited strings, all 0 violations). So restructuring a schema does not help; renaming the colliding property does.This is no longer a problem for us, since we can easily work around it. I would love to hear what the cause/mechanism of this bug is though - I'm really curious.