Finding
The errors reference describes M200 with the wrong HTTP status.
What the docs say
errors.mdx (Limits section): "M200-M203 surface as HTTP 429."
errors/M200.mdx (description): "Returns HTTP 429."
What the platform actually does
A request blocked by a usage-limit rule never gets a 429. enforceLimits returns the M200 text through buildFriendlyResponse, which is always an HTTP 200 chat completion with the error as an assistant message — for every client, SDK callers included (packages/backend/src/routing/proxy/proxy.service.ts:260, proxy-friendly-response.ts).
Live reproduction (local Manifest from main, block rule with threshold $0 on the seeded agent):
POST /v1/chat/completions → HTTP 200
{"object":"chat.completion","model":"manifest","choices":[{"message":{"role":"assistant",
"content":"[🦚 Manifest M200] You hit your cost limit: $9.29 used, $0.00/month allowed. ..."},
"finish_reason":"stop"}]}
By contrast M201 (rate limit) behaves exactly as documented — a real 429 was reproduced after exceeding 200 req/min:
POST /v1/chat/completions → HTTP 429
{"error":{"message":"[🦚 Manifest M201] Too many requests — wait a few seconds and retry. ..."}}
Why it matters: a developer following the docs writes if (status === 429) to detect their spending limits and never sees M200 fire — the response looks like a successful completion.
Secondary findings (same pages)
M200.mdx says the limit metric can be "cost, token, or message-count"; errors.mdx says "Cost or message-count limit". The platform metrics are cost and tokens only (limit-check.service.ts). The Observability page already states it correctly ("Tokens or cost").
errors.mdx says M302 and M303 "both come back as a friendly proxy message". True for chat clients, but M303 is a real HTTP 400 for SDK/tool callers, while M302 is always a 200 friendly message.
Options
A — Fix the docs (smallest change). Rewrite the M200 status wording: M200 is returned as an HTTP 200 chat completion carrying the [🦚 Manifest M200] text as an assistant message; only M201–M203 are HTTP 429. Drop "message-count" from the metric list. Add the M303-is-400-for-SDKs nuance.
B — Align the platform instead. Give M200 the same dual behavior as M204: friendly 200 for chat clients, real 4xx (429) for SDK/tool callers, then keep the docs as written. This is a product decision for mnfst/manifest, not a docs edit — if preferred, this issue should move there and the docs gain the "chat vs SDK" distinction once shipped.
Option A documents today's behavior and can ship immediately; B is arguably the better developer experience but changes the proxy contract.
🤖 Generated with Claude Code
Finding
The errors reference describes M200 with the wrong HTTP status.
What the docs say
errors.mdx(Limits section): "M200-M203 surface as HTTP 429."errors/M200.mdx(description): "Returns HTTP 429."What the platform actually does
A request blocked by a usage-limit rule never gets a 429.
enforceLimitsreturns the M200 text throughbuildFriendlyResponse, which is always an HTTP 200 chat completion with the error as an assistant message — for every client, SDK callers included (packages/backend/src/routing/proxy/proxy.service.ts:260,proxy-friendly-response.ts).Live reproduction (local Manifest from main, block rule with threshold $0 on the seeded agent):
By contrast M201 (rate limit) behaves exactly as documented — a real 429 was reproduced after exceeding 200 req/min:
Why it matters: a developer following the docs writes
if (status === 429)to detect their spending limits and never sees M200 fire — the response looks like a successful completion.Secondary findings (same pages)
M200.mdxsays the limit metric can be "cost, token, or message-count";errors.mdxsays "Cost or message-count limit". The platform metrics arecostandtokensonly (limit-check.service.ts). The Observability page already states it correctly ("Tokens or cost").errors.mdxsays M302 and M303 "both come back as a friendly proxy message". True for chat clients, but M303 is a real HTTP 400 for SDK/tool callers, while M302 is always a 200 friendly message.Options
A — Fix the docs (smallest change). Rewrite the M200 status wording: M200 is returned as an HTTP 200 chat completion carrying the
[🦚 Manifest M200]text as an assistant message; only M201–M203 are HTTP 429. Drop "message-count" from the metric list. Add the M303-is-400-for-SDKs nuance.B — Align the platform instead. Give M200 the same dual behavior as M204: friendly 200 for chat clients, real 4xx (429) for SDK/tool callers, then keep the docs as written. This is a product decision for mnfst/manifest, not a docs edit — if preferred, this issue should move there and the docs gain the "chat vs SDK" distinction once shipped.
Option A documents today's behavior and can ship immediately; B is arguably the better developer experience but changes the proxy contract.
🤖 Generated with Claude Code