Common errors and how to fix them.
mdproof: refusing to execute outside a container (strict mode)
Runbook commands are designed to run inside a devcontainer/Docker.
Cause: mdproof defaults to --strict=true, which refuses to execute commands outside a container for safety.
Fix (pick one):
mdproof sandbox <file> # recommended: auto-provisions a container
mdproof --strict=false <file> # run locally (use with caution)Or set it in mdproof.json:
{ "strict": false }Or set the environment variable:
export MDPROOF_ALLOW_EXECUTE=1jq is not installed (required for jq: assertions)
Cause: jq: assertions require the jq binary on your PATH.
Fix:
# macOS
brew install jq
# Debian / Ubuntu
apt-get install jqOr use mdproof sandbox — the sandbox container includes jq by default.
FAIL jq failed: ...
Common causes:
-
Output is not valid JSON. jq requires strict JSON input. Check for trailing text, ANSI escape codes, or mixed output.
# debug: pipe your command output to jq manually curl -s http://localhost:8080/api | jq .
-
Expression syntax error. jq uses its own expression syntax — string comparisons need quotes:
- jq: .status == "ok" ✓ (quotes around "ok") - jq: .status == ok ✗ (unquoted string)
-
Null vs missing.
.field != nullpasses when the field exists with any value..fieldalone passes when the value is truthy.
snapshot mismatch:
- expected line
+ actual line
Cause: The command output no longer matches the stored snapshot.
Fix:
- If the change is intentional, update the snapshot:
mdproof -u <file>
- If unexpected, check what changed in your command output.
Where snapshots are stored: __snapshots__/<runbook-name>.snap next to your runbook file. Each snapshot is keyed by name — names must be unique within a runbook.
Lifecycle:
- First run → snapshot file is created automatically
- Later runs → output is compared against stored snapshot
- Run with
-u→ snapshot is overwritten with current output
Cause: A step exceeded the per-step timeout (default: 2 minutes).
Fix:
mdproof --timeout 5m <file>Or use a per-step directive:
<!-- runbook: timeout=5m --> ⊘ Step 1 (skipped: setup failed)
Cause: The --setup hook failed, so all steps in that runbook are skipped.
Fix: Check your setup command. Run it manually to debug:
# whatever you passed to --setup
docker-compose up -d && sleep 2Cause: mdproof looks for files matching *_runbook.md, *-runbook.md, *_proof.md, or *-proof.md when given a directory.
Fix: Either rename your file to match the pattern, or pass the file path directly:
mdproof sandbox my-tests.md # explicit file — any name works
mdproof sandbox ./runbooks/ # directory — needs matching patternFAIL expected exit code 0, got 1
Tips:
- When a step has no
Expected:section, mdproof checks for exit code 0 by default. - Use
exit_code: Nto expect a non-zero exit code (e.g., testing error paths). - Sub-commands (
---separated) each have their own exit code. The step exit code comes from the last sub-command.
-
Use
--dry-runto check parsing without executing:mdproof --dry-run <file>
-
Use verbose mode for more detail:
mdproof -v <file> # verbose mdproof -v -v <file> # extra verbose
-
Check the CLI Reference for all available flags.
-
File an issue: github.com/runkids/mdproof/issues