Skip to content

[Hackathon] fix(setup): a timeout while verifying the key is reported as "API key rejected", exit 3, instead of REQUEST_TIMEOUT exit 7 #611

Closed as duplicate

Description

@Andy00L

Verified against (commit SHA or released version)

commit d61e6df (main, v0.15.0), Linux, Node 22

Discord Username / User ID

interferon0

What does this improvement do?

setup checks a key with GET /me before saving it. When that request times out on the client side, setup says the key was rejected and exits 3, the auth family. The same stall on any other command gives REQUEST_TIMEOUT and exit 7.

I reproduced it against a local mock that accepts the connection and never answers:

$ TESTSPRITE_API_KEY=sk-user-... testsprite --request-timeout 2 --output json setup --from-env --no-agent
API key rejected by http://127.0.0.1:35585: Request timed out after 2s (client-side). Use --request-timeout <seconds> or TESTSPRITE_REQUEST_TIMEOUT_MS to extend the deadline. [...] profile NOT updated
{
  "error": {
    "code": "CLI_ERROR",
    "message": "API key rejected by http://127.0.0.1:35585: Request timed out after 2s (client-side). [...] did you mean to set TESTSPRITE_API_URL?",
    "nextAction": "",
    "requestId": "local",
    "details": {}
  }
}
exit=3

$ testsprite --request-timeout 2 --output json project list      # same stalled server
{ "error": { "code": "REQUEST_TIMEOUT", ..., "requestId": "cli_0b3c873d-...", "details": { "timeoutMs": 2000 } } }
exit=7

setup saves nothing in this case. A CI job that runs setup --from-env through a proxy that holds connections open, or against a slow API with a short --request-timeout, fails with "API key rejected" and exit 3, and the natural reaction is to rotate a key that works. The error also loses the typed code, the nextAction, and the cli_… request id the user would send to support.

Details / implementation notes

Root cause. The catch around the ping in runConfigure (src/commands/auth.ts) rethrows InterruptError and any ApiError unchanged and wraps everything else in new CLIError("API key rejected by ...", 3). RequestTimeoutError extends CLIError, not ApiError (src/lib/errors.ts), so the catch wraps it. The comment on that branch only expects "a TypeError from a misconfigured fetchImpl", and the existing test asserts toBeInstanceOf(CLIError) without checking the exit code.

Proposed fix. Rethrow RequestTimeoutError unchanged next to the InterruptError rethrow, or rethrow any CLIError that already carries a typed code, and keep the "profile NOT updated" stderr line. This is the same family as #397 (a preflight timeout reported as exit 1). #470 is the sibling about which deadline this ping uses.

Tests that fail before the fix.

  • setup --from-env against a fetch that never resolves exits 7 with REQUEST_TIMEOUT, keeps the cli_ request id, and writes no credentials.
  • A 401 from /me still exits 3 with the typed envelope.

Confirmations

  • I have searched existing issues and this is not a duplicate.
  • I have provided my Discord identity above for reward coordination.

Activity

  1. Andy00L commented on Oct 20, 2026

    @Andy00L
    ContributorAuthor

    Duplicate of #614, refiled through the hackathon form so it carries the labels.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions