Skip to main content
Start here:
doctor exits 0 when everything passes and 4 when any check fails, so it works in a health-check script. Every failing check prints a concrete fix chosen for how it failed - the same check can fail for different reasons, and a missing binary and a version-drifted one need different commands. --quick skips the slower checks (daemon, harness, index) that need a live subprocess or a filesystem walk. --json gives you the whole report as data.

The checks

Two of those never fail on purpose. A stopped daemon is a choice, not a fault, and being one release behind is not a broken store - reporting them as failures would train you to ignore doctor output. private_folder is reported even when healthy, because the exclusion is invisible in normal use: a brain pointed at a vault with its own work/ folder can have all of it quietly missing from every search.

Fixing each failure

This is the one to fix first. Every workflow depends on it, and doctor invokes your coding agent CLI for real rather than just checking that the binary exists.Three different failures hide behind this check, and the fix differs:
  • Not found. The binary is not on your PATH. Install it, or point model.harness_cmd at the right command.
  • Timed out. The backend is slow or hanging. Try invoking it directly to see whether it is px0 or the CLI.
  • Exited non-zero. The backend itself refused, and usually that means authentication.
To switch backend or model, with verification before saving:
INITIATED means a consent was started and never completed in the browser. Finish it in the tab you already have open, or run the workflow that needs it and px0 will offer a fresh link.There is nothing to reset by hand. If an authorization was revoked at the provider or deleted in Composio, the next run that needs it prepares a new one. See Connections.
An unparseable workflow is one that will never run, so this is a real failure rather than a note. The check names the file and the line, which YAML’s own error does not - it reports the position as <unicode string>.Fix the frontmatter, or move the file out of workflows/ if you are not using it. The rest of your workflows keep working in the meantime: a broken file is skipped, not fatal, and the daemon keeps firing everything else.
Until the index is built, px0 brain ask and px0 brain search have nothing to retrieve from:
On the qmd backend this check reports something different - the qmd version and whether you have consented to the model download:
If your installed qmd has drifted from the pinned version, doctor prints the exact install command, and reminds you that dropping back to the built-in backend is a legitimate answer:
An absent credentials file is fine and passes - it just means you have not stored a connector secret yet.
Wait for the in-flight px0 command to finish and re-run doctor. If nothing is running, the process holding it died without releasing it, and deleting the lock file is safe:
Which side is behind decides the fix.Store behind binary (store 1, binary 2): migrate forward.
Store ahead of binary (store 2, binary 1): this store was written by a newer px0, usually because you rolled back. Upgrade this install to catch up, and avoid writes until you do - schema migrations are forward-only.
Rare, and it means the version manifest database is corrupt. Move it aside and re-run px0 init to rebuild it. Past version content is kept, but the history linking it is lost - so if the store matters, copy the whole .state/versions/ directory somewhere before you do this.
Every freshly initialized store reports this, because px0 init scaffolds starter guidelines before any workflow lists them. It is a nudge, not a problem: px0 guidelines list shows what is there, and px0 guidelines rm <name> clears out one you do not want, keeping its history.
Reported even when everything is fine, because the exclusion is otherwise invisible - a brain pointed at a vault with its own top-level work/ can have all of it quietly missing from every search, ask, and workflow retrieve: input. If that is not what you want, rename or disable the private folder:

Other common situations

”no px0 store at ~/.px0”

You have not initialized one, or PX0_HOME points somewhere unexpected:

A Composio call is refused with a 403 on auth_configs

Your API key is read-only. px0 needs write access to auth_configs to prepare an app’s authorization on your behalf. Grant it on the key in Composio. See Connections.

TLS certificate verification fails on a corporate network

px0 detects a TLS-intercepting proxy when you set the Composio key, finds a system CA bundle that trusts it, and records it as connectors.ca_bundle. If none of the bundles it knows about work, point SSL_CERT_FILE at your corporate root:
px0 will not silently disable verification, so this is the supported path.

A command needs an answer and stdin is exhausted

You piped into an interactive command, or a yes | ran out. Either run it interactively, or pass --yes to accept the defaults.

A scheduled workflow never fired

Work through these in order:
  1. px0 daemon status - is the daemon actually alive, and what does it think the next fire is?
  2. px0 daemon logs - did the tick happen? Log timestamps are UTC; cron is evaluated in machine local time.
  3. px0 runs list --workflow <id> --failed - did it fire and fail rather than never firing?
A missed fire from a closed laptop is not dropped: px0 compares each schedule against its last recorded fire on the next tick and runs what it owes you, marking it late. See Schedules and the daemon.

A workflow’s output is not what it used to be

Open the run in px0 runs and read two fields: the rendered prompt (the exact text the model received) and guidelines inlined, which names each file with the version used. A guideline that changed between the two runs is the most common explanation.

A run failed on its output path

Only {date}, {datetime}, and {time} are substituted, in either brace style. A path that resolves outside the store’s output/ directory is rejected the same way. Both checks exist because the path can come from a model-written plan, so fix the output.path in the workflow’s frontmatter.

Output looks garbled in a pipe or a log

px0 drops colour and animation automatically when it is not writing to a terminal. If something upstream forces colour, disable it explicitly: