What version of Kimi Code is running?
0.26.0 (@moonshot-ai/kimi-code@0.26.0, commit 36b05820cba24e09fdff19a059afc08ccea2c35e)
Which open platform/subscription were you using?
Kimi Code managed OAuth subscription with a billing-cycle usage quota.
Which model were you using?
kimi-code/k3
What platform is your computer?
Darwin 25.5.0 arm64 arm
What issue are you seeing?
When a provider request fails because the billing-cycle usage quota is exhausted, Kimi Code detects and logs the failure internally, but its ACP adapter resolves session/prompt successfully with stopReason: "end_turn".
The ACP client therefore receives no error and cannot tell the user that quota was exhausted. From the client side, the turn looks like an empty successful completion or a stalled conversation.
This is a quota failure, not an authentication or permission failure.
Internal Kimi Code log:
llm request failed ... errorName=APIStatusError errorMessage="403 You've reached your usage limit for this billing cycle. Your quota will be refreshed in the next cycle." statusCode=403
acp: turn ended with failed reason error={"code":"provider.api_error","name":"APIStatusError","details":{"statusCode":403,"turnId":2},"retryable":false}
ACP-observed result:
{
"stopReason": "end_turn"
}
No machine-readable provider or quota error reaches the ACP client.
What steps can reproduce the bug?
- Log in to Kimi Code using a quota-based managed subscription.
- Start Kimi Code as an ACP agent with
kimi acp and connect an ACP client.
- Exhaust the billing-cycle quota.
- Send another prompt through the ACP client.
- Compare the Kimi Code log with the
session/prompt JSON-RPC result.
Kimi Code logs a turn.ended event with reason: "failed" and a non-auth provider.api_error, while the ACP request resolves normally as end_turn. Repeating the prompt produces the same result.
What is the expected behavior?
A turn.ended event with reason: "failed" should be surfaced through the ACP/JSON-RPC error channel, with safe machine-readable fields such as the provider error code, HTTP status, and retryability. The ACP client should be able to display the quota message and mark the turn as failed.
It should not be converted into a successful end_turn. Authentication failures can keep their existing authRequired handling.
Additional information
The behavior appears to be explicitly implemented and covered by a test:
The same path is still present on the current main branch. I could not find an existing issue that combines quota exhaustion with the ACP failure being swallowed as end_turn.
What version of Kimi Code is running?
0.26.0(@moonshot-ai/kimi-code@0.26.0, commit36b05820cba24e09fdff19a059afc08ccea2c35e)Which open platform/subscription were you using?
Kimi Code managed OAuth subscription with a billing-cycle usage quota.
Which model were you using?
kimi-code/k3What platform is your computer?
Darwin 25.5.0 arm64 armWhat issue are you seeing?
When a provider request fails because the billing-cycle usage quota is exhausted, Kimi Code detects and logs the failure internally, but its ACP adapter resolves
session/promptsuccessfully withstopReason: "end_turn".The ACP client therefore receives no error and cannot tell the user that quota was exhausted. From the client side, the turn looks like an empty successful completion or a stalled conversation.
This is a quota failure, not an authentication or permission failure.
Internal Kimi Code log:
ACP-observed result:
{ "stopReason": "end_turn" }No machine-readable provider or quota error reaches the ACP client.
What steps can reproduce the bug?
kimi acpand connect an ACP client.session/promptJSON-RPC result.Kimi Code logs a
turn.endedevent withreason: "failed"and a non-authprovider.api_error, while the ACP request resolves normally asend_turn. Repeating the prompt produces the same result.What is the expected behavior?
A
turn.endedevent withreason: "failed"should be surfaced through the ACP/JSON-RPC error channel, with safe machine-readable fields such as the provider error code, HTTP status, and retryability. The ACP client should be able to display the quota message and mark the turn as failed.It should not be converted into a successful
end_turn. Authentication failures can keep their existingauthRequiredhandling.Additional information
The behavior appears to be explicitly implemented and covered by a test:
packages/acp-adapter/src/session.tsrejects authentication failures, but logs and resolves all otherturn.ended(reason="failed")events.packages/acp-adapter/src/events-map.tsmapsfailedtoend_turn.packages/acp-adapter/test/error-mapping.test.tscalls the non-auth behavior a “log-only path” and asserts that the request resolves.The same path is still present on the current
mainbranch. I could not find an existing issue that combines quota exhaustion with the ACP failure being swallowed asend_turn.