Skip to main content
zespan doctor runs a fixed set of checks against your project and prints a pass/warn/fail/skip summary. It exists for one specific, common failure: a customer installs the SDK, sees nothing in the dashboard, and has no way to tell whether the problem is their API key, their network, their code, or nothing at all (a project that just hasn’t sent its first trace yet).

Quick start

With no flags, doctor reads ZESPAN_API_KEY from the environment and .zespan.yaml from the current directory — see CLI overview for the full precedence rules. Self-hosted deployments should also pass --api-url (or set ZESPAN_API_URL).

What it checks

Checks run in a fixed order, grouped under four headings. Every fail or warn result comes with at least one actionable fix line, printed indented under it ().

Configuration

Confirms the key authenticates and reports which project it belongs to. This is the first check, and the only one whose failure short-circuits every check below it (see Short-circuit on a bad key).
  • passValid — project "<name>" (<id>)
  • fail — the key was flatly rejected (HTTP 401). Fix: double-check ZESPAN_API_KEY / --api-key against Settings → API Keys, or rotate if the key was revoked.
  • skip — a network failure, not a rejected key (DNS, TLS, timeout, connection refused). Fix: check connectivity and any corporate proxy.
Independent of the whoami call — this hits the API host’s root /health route, so it still runs and gives a useful second data point even when the key check above failed on the network (not on the key).
  • pass<host> responded in <ms>ms
  • fail — names the host it couldn’t reach, and lists any HTTP_PROXY / HTTPS_PROXY / NO_PROXY (or lowercase) environment variables that were set at the time — or says none were set, since an unconfigured egress proxy on a corporate network is a common cause.
Reports the resolved --env / ZESPAN_ENVIRONMENT / .zespan.yaml environment value, or skip if none is configured. Purely informational — there’s nothing to pass or fail here.

SDK

Compares the @zespan/sdk version against the latest version the API reports. When node_modules/@zespan/sdk/package.json is readable, compares the ACTUALLY RESOLVED installed version; otherwise falls back to the range declared in your package.json (dependencies or devDependencies, e.g. ^1.0.0) and labels it “declared range” rather than “installed”, since a range’s floor isn’t necessarily what’s really installed.
  • skip@zespan/sdk isn’t a dependency at all (a Python-only or OTel-native project is expected to skip this), or the API didn’t report a latest version to compare against.
  • warn — the compared version is behind. Fix: pnpm add @zespan/sdk@latest.
  • pass — up to date.

Data flow

Checks whether spans have actually arrived recently, using the project id you configured (or the one your API key resolves to). Reports a fail once your integration has gone more than 15 minutes without a span, with the last-seen timestamp and 24h span count.A lastSpanAt of null — no span in the last 90 days — is reported as skip, not fail: the API bounds this query to a 90-day lookback for ClickHouse partition pruning, so a brand-new project that hasn’t sent its first trace yet and a project whose integration went quietly dead over 90 days ago are indistinguishable from this response alone. doctor says so explicitly rather than guessing, and gives a fix path for both readings.If --project/ZESPAN_PROJECT_ID names a project that doesn’t match the one your API key actually belongs to, this check fails with a plain message naming both project ids — one of the five causes doctor exists to diagnose — instead of the raw HTTP 403: {"error":"API key does not match the requested project"} the API returns.Any ingest rejections recorded for the project are folded into the detail and fix lines by reason and count.

Policy & redaction

Reads the project’s resolved redaction policy from the same whoami call.
  • pass — the server reports redaction as on (names the preset, if one is set).
  • skip — the server didn’t report a redaction policy at all, OR reported it as off. The server-side policy has no way to be changed today, so doctor never warns about it — a warning a user has no way to clear is worse than no check at all. The skip detail still names the real, working client-side fix (zespan.init({ redactPii: true }), optionally scoped with a preset: gdpr, hipaa, ccpa, pci-dss, soc2, finance, education, or transportation) in case your SDK is already configured that way — client-side redaction happens before data reaches the API, which this check can’t see.

Wrapper ordering: a heuristic, not a guarantee

A provider client (OpenAI, Anthropic, Mistral, Groq, Cohere, GoogleGenAI) constructed before zespan.init() runs never gets patched by the SDK — every call it makes is invisible to Zespan. This is the single most common cause of “I installed the SDK and see nothing,” so doctor scans your project’s source files (TypeScript, JavaScript, and Python; up to 500 files, 8 directories deep, skipping node_modules/dist/.venv and similar) looking for it. The rule it applies is deliberately narrow: it only flags a provider constructor at module scope (zero leading indentation — not inside a function, method, or class body) in a file where zespan.init( does not appear on an earlier line of that same file.
This is a heuristic and it can produce false positives. The check reads one file at a time — it has no way to know that zespan.init() already ran in a different module that got imported first. If your actual entry point calls zespan.init() before it imports the file doctor flagged, the provider client in that file genuinely runs after init and the warning is a false positive.How to tell: trace your own import graph. If the module that calls zespan.init() is imported (directly or transitively) before the flagged file anywhere in your app, you’re safe — the flagged construction really does run after init, doctor just can’t see across files to confirm it. If you can’t establish that ordering, treat the warning as real.

Sample output

This is real output from zespan doctor run with no configured API key (ZESPAN_API_KEY unset), showing the short-circuit behavior described below:

Behaviors worth knowing

1

Short-circuit on a bad key, not a cascade

If the API key check itself reports fail (the key was flatly rejected — a 401, not a network problem), every later check is marked skip without ever running. Six confusing failures caused by one bad key is a worse diagnostic experience than one clear failure, so doctor stops there. This only triggers on apiKeyValid specifically failing — a network failure (skip, not fail) does not short-circuit; API reachability still runs independently and gives you a second data point.
2

A check never crashes doctor

If a check throws for any reason, doctor catches it and reports that check as fail carrying the thrown message, instead of the whole command crashing. doctor is the tool people reach for when something is already broken — it has to stay usable when things go wrong in unexpected ways.
3

Warnings never affect the exit code

Only a fail anywhere in the results makes doctor exit 1. A warn — a stale SDK version, redaction disabled — is real, actionable advice, but it is not a broken setup, and a CI job gating on doctor’s exit code must not be blocked by advice it can’t act on immediately.

--json output

zespan doctor --json prints exactly one JSON line — { results, summary } — and suppresses the grouped-text renderer, for CI consumption.
Real output from the same unauthenticated run shown above:

Flags

string
Your Zespan API key. Falls back to ZESPAN_API_KEY. Never read from .zespan.yaml.
string
Project id, if it differs from the one your API key resolves to. Falls back to ZESPAN_PROJECT_ID or .zespan.yaml’s project.
string
Environment name for the Environment check. Falls back to ZESPAN_ENVIRONMENT or .zespan.yaml’s environment.
string
default:"https://api.zespan.com/v1"
Override the API base URL. Falls back to ZESPAN_API_URL. Never read from .zespan.yaml (same treatment as --api-key — see CLI overview). Needed for a self-hosted deployment.
boolean
Print { results, summary } as a single JSON line instead of grouped text, and disable colour output.
boolean
Print this command’s usage and exit — does not run any checks or make any network calls.
See CLI overview for the full flag/env/file precedence rules.

Next steps

CLI overview

Installation, .zespan.yaml, and environment variables.

Troubleshooting

Symptom-first fixes for missing traces, broken span trees, and $0.00 cost.

PII redaction

Configure redactPii and choose a preset.

API keys

Create and rotate the key doctor authenticates with.

zespan auth

A separate credential, for the commands that act as a person rather than a project.