Troubleshooting

June 14, 2026 · View on GitHub

How to read failures

capctl prints errors to stderr as Error (CODE): message (or JSON with --json) and exits with a code that tells you the failure class:

Exit codeClassTypical cause & fix
1Internal/unexpectedRe-run with --verbose; if it persists, open an issue with the output
2Invalid inputA flag or argument failed validation — check --help for the command
3Configuration.env missing or incomplete — see below
4Safety policyTrading disabled / confirmation missing / EPIC not allowed / risk limit
5AuthenticationWrong credentials or expired session — see below
6Local rate limitYou're sending commands too fast; wait a second
7Broker / upstreamCapital.com rejected the request (market closed, insufficient funds, outage)
8Preview problemPreview id wrong, older than 2 minutes, or its checks failed

Common problems

capctl: command not found

The virtualenv isn't active. Run source .venv/bin/activate (Windows: .venv\Scripts\activate), or install globally with pipx install ..

Exit 3: "Field required" mentioning cap_api_key / cap_identifier / cap_api_password

The CLI can't find your credentials. Confirm .env exists in the directory you're running from (or pass --env-file /path/to/.env), and that all three values are filled in.

Exit 5: authentication failed

  • CAP_API_PASSWORD must be the custom password you set when generating the API key, not your Capital.com account password.
  • The API key may be expired or revoked — generate a new one in Settings → API integrations.
  • Check you're on the right environment: a demo key won't work with --live and vice versa.

Exit 4: "Trading is disabled"

Set CAP_ALLOW_TRADING=true in .env — and list the markets you want in CAP_ALLOWED_EPICS (e.g. GOLD,BTCUSD, or ALL).

Exit 4: "Explicit confirmation required"

Add --yes to the command. This is deliberate friction for anything that changes state.

Exit 4: "Epic 'X' not in allowlist"

Add the EPIC to CAP_ALLOWED_EPICS in .env.

Exit 8: "Preview ... expired"

Previews are valid for 120 seconds. Run the preview command again and execute the fresh preview_id.

Exit 7 on execute: market closed / rejected

Stock and commodity markets have trading hours; try a 24/7 market like BTCUSD to verify your setup, or retry during market hours. The confirmation message from the broker (shown in the output) says why.

HTTP 429: error.too-many.requests on login

Capital.com limits how often you can create sessions. Wait a couple of minutes and try again. Scripts that fire many capctl commands in a tight loop should pause ~1 second between them. By default capctl caches the short-lived session token (CAP_PERSIST_SESSION=true) so back-to-back commands reuse one login instead of re-authenticating each time, which is the main mitigation for this error; keep it enabled (set CAP_PERSIST_SESSION=false only if you need in-process-only tokens).

WebSocket streaming is disabled

Set CAP_WS_ENABLED=true in .env. Streaming also requires valid login credentials.

Streaming shows no ticks

Quiet markets tick rarely outside their trading hours. Try BTCUSD, which trades around the clock.

Where is my state stored?

Trade previews, the daily order counter, and (by default) the cached short-lived session token persist in ~/.config/capital-cli/state.json (mode 0600, override with CAPCTL_STATE_FILE) so they survive between commands. Deleting the file is safe (you'll just lose unexecuted previews and have to log in again). Your API key/password are never written there.

Still stuck?

Run the failing command with --verbose and open a GitHub issue including the command, the output (it never contains your secrets), and your OS and Python version.