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
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. Everyfail or
warn result comes with at least one actionable fix line, printed indented
under it (→).
Configuration
API key — calls GET /v1/sdk/whoami
API key — calls GET /v1/sdk/whoami
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).
- pass —
Valid — project "<name>" (<id>) - fail — the key was flatly rejected (HTTP 401). Fix: double-check
ZESPAN_API_KEY/--api-keyagainst 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.
API reachability — GET /health
API reachability — GET /health
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.
Environment
Environment
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
SDK version
SDK version
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/sdkisn’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.
Wrapper ordering — the most common cause of "I see nothing"
Wrapper ordering — the most common cause of "I see nothing"
Data flow
Data flow — calls GET /v1/projects/:id/ingest-health
Data flow — calls GET /v1/projects/:id/ingest-health
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
PII redaction
PII 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
doctorneverwarns 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, ortransportation) 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.
Sample output
This is real output fromzespan 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.
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.
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.

