Skip to main content

unknown provider: minimax: an error your agent couldn't recover from

· 3 min read
Tosin Akinosho
Helmdeck maintainer

A content.ground call failed like this:

handler_failed: claim extractor dispatch: unknown provider: minimax: unknown provider: minimax

The agent had picked model: "minimax/abab6.5". It's a reasonable-looking guess — MiniMax is a real provider, and OpenRouter's model catalog literally lists minimax/minimax-m2.7. But helmdeck's gateway has no minimax provider: MiniMax is reachable only through OpenRouter, as openrouter/minimax/minimax-m2.7. Drop the openrouter/ prefix and you land on a provider that doesn't exist.

That part is a normal mistake. What made it bad was the shape of the failure.

handler_failed is a dead end

helmdeck's packs return typed error codes so an agent can branch on the failure instead of parsing prose. handler_failed is the code reserved for buried exceptions — a handler panicked or returned something uncategorized. By contract it means "something broke inside; not your fault, not your fix."

So when the gateway's "unknown provider" error got wrapped as handler_failed, we told the agent exactly the wrong thing. A bad model string is the most caller-fixable failure there is — but the code said "unrecoverable," carried no hint about what was valid, and (thanks to a double-wrap bug) repeated itself. Faced with that, a model does the worst possible thing: it shrugs and guesses another model. We were manufacturing hallucinated retries.

Two changes: classify it, and offer a list

The fix has a reactive half and a proactive half.

Reactive — make the error caller-fixable. A shared helper now classifies a gateway dispatch failure. If it's an unknown provider or a malformed model string, it becomes invalid_input — the code that means "you can fix this and retry" — with a message that says how:

invalid_input: claim extractor dispatch: unknown provider: minimax —
pick a configured model from the helmdeck://models resource (or GET
/v1/models); use the full provider/model id, e.g.
openrouter/minimax/minimax-m2.7, not minimax/…

Everything else still maps to handler_failed. And the detail now lives in one place (the message), so it doesn't print twice.

Proactive — give the agent the actual list. There was no way to discover valid chat models the way helmdeck://voices and helmdeck://image-models already let agents discover TTS voices and image models. So there's a new MCP resource, helmdeck://models, backed by the gateway's live registry — every routable provider/model ID, including openrouter/minimax/minimax-m2.7. The error points at it; so do the pipeline-builder tool and the agent skill. The agent reads it and picks a real model up front.

The thing worth generalizing

We didn't add MiniMax as a provider. The bug was never "MiniMax isn't supported" — it's reachable, just under a different name. The bug was that the failure didn't tell anyone that.

The lesson is about error design for agents specifically: an error code is a contract about recoverability, and putting a caller-fixable failure under a not-your-fault code is worse than no code at all, because a capable model will trust the contract and act on it — by giving up and guessing. When a failure is the caller's to fix, say so, and say what "fixed" looks like. The cheapest way to stop a model hallucinating an answer is to hand it the real one.

See the content.ground reference for the model input and error codes, and ADR 043 for the decision.