feat(chat): show a quota hint when the server's key is refused

On the server's own credentials a provider 403 now gets its own code,
server_key_forbidden, with a hint in all four languages: today's free
quota is used up, it resets tomorrow, and users can add their own key
in model settings. The generic "The provider returned an error." line
is left out for this code.

A daily spend cap that blocks a shared key makes every call return 403.
The old hint said the key may lack access to the model or region, which
points users at a setting they cannot change.

A 403 on the user's own key keeps the old hint and the provider's text.
This commit is contained in:
dayuan.jiang
2026-10-06 09:23:41 +09:00
parent 38b72e89b6
commit 149ed34b9e
9 changed files with 67 additions and 6 deletions
+19 -1
View File
@@ -215,11 +215,29 @@ describe("streamErrorText", () => {
"User: arn:aws:sts::123456789012:assumed-role/app/s is not authorized to perform: bedrock:InvokeModel",
)
const hidden = JSON.parse(streamErrorText(error, true))
expect(hidden.code).toBe("forbidden")
expect(hidden.message).not.toMatch(/arn:aws|123456789012/)
expect(JSON.parse(streamErrorText(error)).message).toMatch(
/not authorized/,
)
const throttled = JSON.parse(
streamErrorText(apiError(429, "Too many tokens"), true),
)
expect(throttled).toEqual({
type: "provider",
code: "rate_limited",
message: "The provider returned an error.",
})
})
it("names a 403 on the server's keys, e.g. a spend cap blocked them", () => {
const error = apiError(403, "explicit deny in an identity-based policy")
expect(JSON.parse(streamErrorText(error, true))).toEqual({
type: "provider",
code: "server_key_forbidden",
message: "",
})
// On the user's own key it stays a plain refusal
expect(JSON.parse(streamErrorText(error)).code).toBe("forbidden")
})
it("classifies a provider error", () => {