urna doctor
Reference for urna doctor, the offline install check that tests the Python env, the potion embedder and one real embed, and exits with a typed code.
urna doctor checks everything ask and retrieve depend on for potion corpora: the Python interpreter, numpy and tokenizers, the embedder script, the potion table, and one real offline embed of a probe string. It exits with the code of the first failing check, so scripts and installers can branch on the failure class. It makes no network request.
Unlike the other engine verbs, doctor runs Python: it starts the interpreter up to three times.
Usage
urna doctorOptions
| Option | Default | Description |
|---|---|---|
-h, --help | Print help. |
Checks
The checks run in this order. Two of them stop the list, because the checks after them need what they found.
| # | Check | Passes when | Fails with | Stops the list |
|---|---|---|---|---|
| 1 | version | always; prints urna <version>, format v1 | ||
| 2 | simd | a SIMD backend is active (neon, avx2) | never fails; the scalar fallback is a warning and the exit code stays 0 | |
| 3 | python | <interpreter> --version runs and prints a version | 2: "not runnable: <interpreter> (set URNA_PYTHON, or run urna setup)" | yes |
| 4 | python deps | <interpreter> -c "import numpy, tokenizers" succeeds | 3: "numpy and/or tokenizers missing (run urna setup, or uv pip install numpy tokenizers)" | no |
| 5 | embedder | embed_query_potion.py resolves to an existing file | 4: "not found (looked in the repo layout and <data dir>/urna/forge)" | yes |
| 6 | potion table | <embedder dir>/models/potion-base-8M/model.safetensors exists and is not a git-lfs pointer | 5: the file is a git-lfs pointer ("run git lfs pull"), or it is missing | no |
| 7 | embedder run | <interpreter> <embedder> potion-base-8M "urna doctor probe" exits 0 with JSON whose embedding_dim is above 0 and equals the vector length, and whose model_hash starts with sha256: | 6: the script exited non-zero or printed invalid JSON, or the JSON breaks that contract |
Check 7 runs only when check 4 passed; otherwise it shows as a warning, "skipped (python deps missing)".
Because the first failure decides the code, a machine with Python but without numpy exits 3 even when the embedder is also missing. Code 4 appears only when the interpreter already has both packages. No check looks at the Python version.
The interpreter, the embedder script and the table are found with the lookup orders in paths: URNA_PYTHON, then the venv urna setup builds, then the nearest .venv, then python3; and the repo layout first, then each data directory's urna/forge/. The table must sit next to the script that was found, in models/potion-base-8M/.
Output
urna doctor prints to stdout one line per check with a tag (ok, warn or fail(N)), then urna doctor: ok or urna doctor: failed. Every failure except 6 adds a hint line. On stderr it prints the chosen interpreter as [urna] embedder interpreter: <path>, and, when the probe failed, the embedder's error as embedder stderr: <text>.
Color is used only when stdout is a terminal, so piped output has no escape codes. NO_COLOR or URNA_COLOR=none turn it off on a terminal too.
A machine set up with urna setup:
urna doctor
[urna] embedder interpreter: /Users/nn/.local/share/urna/venv/bin/python
ok version: urna 0.5.1, format v1
ok simd: neon
ok python: /Users/nn/.local/share/urna/venv/bin/python (Python 3.12.14)
ok python deps: numpy, tokenizers
ok embedder: /Users/nn/.local/share/urna/forge/embed_query_potion.py
ok potion table: /Users/nn/.local/share/urna/forge/models/potion-base-8M/model.safetensors (30.2 MB)
ok embedder run: dim=256 model_hash=sha256:8f2eb91a754b4da59cdd8223d0ba196185fed1bb6f092fd2be0ff02b893b1c98
urna doctor: okAn interpreter pinned to a path that does not exist:
urna doctor
[urna] embedder interpreter: /nonexistent/python
ok version: urna 0.5.1, format v1
ok simd: neon
fail(2) python: not runnable: /nonexistent/python (set URNA_PYTHON, or run `urna setup`)
urna doctor: failed
next: `urna setup` lays down the embedder and a python envExit codes
| Code | Meaning | Usual fix |
|---|---|---|
0 | every check passed (a scalar SIMD warning still exits 0) | |
2 | the Python interpreter is missing or does not run | urna setup, or set URNA_PYTHON |
3 | numpy or tokenizers is missing from the interpreter | urna setup, or install both in that interpreter |
4 | the embedder script was not found | urna setup |
5 | the potion table is missing or is a git-lfs pointer | urna setup; in a repo checkout, git lfs pull or sh scripts/fetch_potion.sh |
6 | the embedder ran but failed or broke the JSON contract | read the embedder stderr line |
urna setup ends with the same checks and returns the same codes when they fail; see urna setup.
In a repo checkout, the checkout's embedder always wins the lookup, so a git-lfs pointer there keeps failing with 5 no matter how often you run urna setup.
Examples
Branch on the code in a provisioning script:
urna doctor > /dev/null 2>&1
case $? in
0) echo "ready" ;;
2|3|4) urna setup --yes ;;
5) urna setup --yes --force ;; # an embedder is present, so only --force replaces its table
*) echo "embedder run failed: run urna doctor for the error" ;;
esacCheck a specific interpreter before pinning it:
URNA_PYTHON=/opt/py312/bin/python urna doctorSee the scalar SIMD warning (the exit code stays 0):
URNA_FORCE_SCALAR=1 urna doctorurna benchmark
Reference for urna benchmark, which times exact search on random query vectors, and optionally HNSW with recall@k, a cold-cache pass, or a named space.
urna setup
Reference for urna setup, the installer that lays down the offline embedder payload and a Python env, then proves the install with the doctor checks.