Skip to main content
Run testsprite doctor first. It checks your CLI version, Node runtime, profile, endpoint, credentials, connectivity, and verify-skill install.
The binary isn’t on your PATH. Check node --version (20.19+, 22.13+, or 24+; 21.x and 23.x are unsupported), then run npm install -g @testsprite/testsprite-cli, or use npx @testsprite/testsprite-cli --version.
The key is missing, invalid, or lacks a scope. Run testsprite auth status, then reconfigure with testsprite setup --no-agent (or TESTSPRITE_API_KEY=sk-... testsprite setup --from-env --yes --no-agent). On AUTH_FORBIDDEN, details.requiredScope names the missing scope. Scopes follow your role in the key’s workspace: a Viewer’s key is refused everything, so ask an Admin or the Owner to make you a Member (Members & Roles). A key also stops working when you leave or are removed from its workspace. In CI, TESTSPRITE_API_KEY overrides the credentials file.
project create|update --url and project env create|update --url accept a public http(s) URL or, for a frontend project, a loopback http origin with an explicit port and no path (http://localhost:3000, http://127.0.0.1:3000, http://[::1]:3000). They refuse https loopback, 0.0.0.0, link-local, RFC 1918 addresses, and any loopback URL on a backend project.To test a local app, see Test an app on your machine. To move a local-only project to a deployed site, use --target-url on a single run, or testsprite project update <project-id> --url https://app.example.com to change the Default environment. project env create fails with exit 13 (FEATURE_GATED) on Free and Starter, which allow one environment per project.
Exit 5: the URL is not a public http(s) address or a loopback http origin with a port, it is combined with --local, or the reachability probe found the host clearly unreachable. If the probe is wrong for your network, pass --skip-preflight.Exit 6, frontend-auth-target-origin-mismatch: the environment that supplies the sign-in (the one passed with --env, or a Default with a recorded session) uses a recorded browser session, OTP, or login-once step, and the target is on a different origin. Nothing is charged. Use an environment whose URL has the target’s origin, or save the target as an environment. See Running Tests.
  • Ordinary run, or a --local run adopted via --tunnel-client: not a failure. The run is still going; resume with testsprite test wait <run-id> --timeout 600 --output json.
  • Self-started --local run (default): the timeout requests cancellation and closes the tunnel. Check the reported outcome (status: "cancelled"); if cancellation failed, run testsprite test cancel <run-id>. Then start a new run with a longer --timeout, because test wait cannot reopen the tunnel. Credits may already be charged.
  • With --no-cancel-on-interrupt: nothing was cancelled. The run keeps going and billing in the cloud, and steps that need your machine fail. Check it with test wait <run-id>, or stop it with testsprite test cancel <run-id>.
See Cancelling Runs.
details.reason says why:
  • no_failing_run: the run passed.
  • run_not_terminal (exit 6): the run is still going; use testsprite test wait <run-id>.
  • cancelled_no_artifacts: the run was cancelled first.
  • no_code: the bundle is built from saved code, and none exists. A frontend test that has never passed, or has only run with --local, has none.
For no_code and cancelled_no_artifacts, use testsprite test steps <test-id> --run-id <run-id> and testsprite test failure summary <test-id>.
The code changed since you fetched it. Run testsprite test code get <test-id>, reapply your edit, and put again. --expected-version <v> pins a version; --force skips the guard (last writer wins).
test delete, test delete-batch, and tunnel stop --all need --confirm; without it the CLI exits 5 before any request. --max-concurrency accepts 1–10 when a tunnel is in use; a larger value is refused before any run starts.
Each user can have 5 live tunnel bindings across all keys. This error is not retried automatically. Run testsprite tunnel list, then testsprite tunnel stop <client-id> for an unused one. tunnel stop --all --confirm revokes every binding, including ones other terminals or CI jobs are using. Bindings that are provably dead are released automatically before the limit is enforced.
The per-key run-rate limit shed some work. Back off and retry; the CLI already retries a few times. For a batch rerun, retry the tests listed in deferred[] with a fresh --idempotency-key.
Not retriable. testsprite usage shows which workspace the key draws on and its balance. An Admin or the Owner of that workspace buys extra credits from Workspace Settings → Billing → Usage in the web portal.
Every write and run is refused, with details.reason: "paused", while the key’s workspace is paused: its paid subscription ended while the workspace still needed a paid plan. auth status and usage show the notice and a billing link. Topping up doesn’t resume it; the Owner renews, picks another plan, or downgrades to Free from Settings → Plan. See Plans and Pausing.
Append --dry-run --output json. It makes no network calls or file writes and returns canned data in the real response shape.

Still stuck?

Discord

Join the community.

Issues & feature requests

File a bug or request a feature on GitHub.

In the terminal

Run testsprite --help or testsprite <command> --help.