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 #614

Open

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. fyZhang66 commented on Oct 22, 2026

    @fyZhang66
    Contributor

    Confirmed on v0.15.0, thanks @Andy00L. runConfigure's catch around the /me check (auth.ts:299-320) wraps every non-ApiError in an exit-3 "API key rejected" error, and RequestTimeoutError extends CLIError, not ApiError, so a timeout during setup tells the user their key was rejected and to check TESTSPRITE_API_URL.

    Accepted, scope:

    • Rethrow RequestTimeoutError unchanged (exit 7, REQUEST_TIMEOUT, request id kept), and make the stderr line say the check timed out rather than "rejected". Keep "profile NOT updated".
    • Tests (each must fail before the fix): setup --from-env against a fetch that never resolves exits 7 with REQUEST_TIMEOUT and writes no credentials; a 401 from /me still exits 3 with the typed envelope.

    No new dependency. Comment /assign to claim it.

  2. added
    acceptedTriaged and accepted — a PR for this will be reviewed
    and removed
    needs-triageNew issue/PR awaiting first triage
    on Oct 22, 2026
  3. Lexiie commented on Oct 22, 2026

    @Lexiie
    Contributor

    /assign

  4. testsprite-hob commented on Oct 22, 2026

    @testsprite-hob

    Thanks for the interest, @Lexiie! @Andy00L opened this issue, so it's reserved for them until 2026-10-24T07:08:47Z (48 hours after it was accepted). If they haven't claimed it by then, comment /assign again.

  5. Andy00L commented on Oct 22, 2026

    @Andy00L
    ContributorAuthor

    /assign

  6. testsprite-hob commented on Oct 22, 2026

    @testsprite-hob

    Assigned to @Andy00L. Thanks for taking this on. (0 more slots available.)

    Your open assigned issues (3/3):

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

Metadata

Metadata

Assignees

Labels

acceptedTriaged and accepted — a PR for this will be reviewedhackathonCLI hackathon submissionsin-progressAssigned and actively being worked on

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions