Skip to content

Troubleshooting

!!! info "TL;DR" Most CLI errors map to one of six exit codes. This page covers the failure modes that aren't obvious from the error text alone: 401 vs 403, the 422 unrecognized-key error, NO_COLOR, and rate limits.

401 vs 403

survey, question, and trigger commands call the same MCP tool endpoint and treat 401 and 403 the same way: both exit with code 3 (AUTH). The distinction still matters for diagnosis.

401, invalid or missing credential. You saw one of these:

  • Missing or invalid Authorization header. Use: Bearer pk_live_..., no credential was resolved at all
  • Invalid API key, the key doesn't match anything on the server
  • API key has expired
  • Invalid or expired session token / Session token has been revoked, a cached session token (see Authentication) was rejected; the CLI retries once with your pk_* key automatically, so this message means the pk_* key itself failed too

Fix: run canviq auth login, or check that CANVIQ_API_KEY is set and correctly copied (no trailing whitespace, no truncation from a shell quoting issue).

The most common cause of Invalid API key specifically: the key was not generated from Settings → Agents (/admin/settings/agents). An SDK key or a key created via the generic API Keys wizard has the same pk_live_/ pk_test_ look but no agent attached to it, and every canviq command rejects it. See Authentication → Getting an agent-backed key.

403, valid credential, not authorized. You saw one of these:

  • Agent is not active, the agent behind this key was suspended; contact your org admin
  • Insufficient permissions to invoke this tool. / a message naming a missing scope, the key doesn't have the scope the command needs (for example, surveys:write for question create). Regenerate the key with the required scope
  • Access denied, the request came from a blocked source

canviq survey commands show shorter first-party copy for both cases (Not authenticated... / ...does not have the required scope...); question and trigger commands show the server's message directly. Either way, the exit code is 3.

canviq audit-logs is the one command that does not follow this pattern: it calls a separate REST endpoint (not the MCP tool endpoint) and only maps 403 to exit code 3. A 401 from that endpoint falls through to the generic Error: unexpected response from API (HTTP 401). message at exit code 1, not 3. See Audit Logs for the rest of that command's error handling.

422 unrecognized-key errors

POST /api/mcp/tools (the endpoint every survey, question, and trigger command calls) validates its request body against a strict schema: only tool and arguments are allowed at the top level. A request with any other top-level key, most commonly a leftover input key from an older client contract, is rejected with a 422 response naming the offending key directly, for example:

Error: Validation Error
Unrecognized key(s) in object: 'input'

The shipped CLI always sends the correct { tool, arguments } shape, so you will not see this from canviq itself. It shows up if you or an agent call POST /api/mcp/tools directly with a hand-built request body. The CLI's shared error handling doesn't special-case 422; it falls into the generic 4xx bucket and exits with code 1 (GENERAL), not a dedicated code.

Exit code contract

The CLI's exit codes are the authoritative script-facing contract. Full table and examples: Scripting and CI → Exit codes. The exit-code definitions live in the public canviq-cli source.

Code When you'll see it in practice
0 Success, including "insufficient responses" on survey pmf-score
1 Network errors, malformed server responses, 422s, and any error path a command doesn't map to a specific code
2 A flag is missing, malformed, or out of range, checked before any network call
3 401 or 403 from the MCP tool endpoint (see above)
4 The requested survey, question, or trigger ID doesn't exist
5 Rate limited, see below

NO_COLOR

Setting NO_COLOR to any non-empty value disables ANSI color in table output, including NO_COLOR=0. The check is a truthiness test on the environment variable, not a comparison against "0" or "false". To restore color, unset the variable entirely:

unset NO_COLOR

Setting it to an empty string (NO_COLOR=) also restores color, an empty string is falsy, so this is indistinguishable from unset. Color is only ever shown on a TTY in the first place; --json, --quiet, and non-TTY output (piped, redirected, CI) never include color regardless of NO_COLOR.

429 rate limits

Two independent rate limiters can return 429, both map to exit code 5 and both include a Retry-After header that the CLI prints.

MCP tool endpoint (survey, question, trigger commands). The limit depends on your agent's assigned tier: 30 requests/minute on the default (readonly) tier, 300/minute on growth, 1000/minute on scale. Contact support to raise your tier if you're hitting this in normal usage.

Audit log endpoint (audit-logs command). Fixed at 60 requests/hour regardless of tier. See Audit Logs.

For a retry loop pattern, see Scripting and CI → Handling rate limits.

Report a bug or get help

Hit something this page doesn't cover? File it in the public canviq-cli issue tracker. Include the command you ran, the full output, the exit code, and your CLI version from canviq --version. That is enough to reproduce most problems without a back-and-forth.