Doctor¶
decentdb doctor inspects a DecentDB database and returns a deterministic health report for humans, automation, and support workflows. It is read-only by default and can optionally run a small, explicit catalog of safe repair actions with --fix.
Use Doctor when you want to answer questions like:
- Is this database readable by the current engine?
- Is the WAL growing because checkpoints are blocked or delayed?
- Are indexes stale or logically inconsistent?
- Is the file fragmented enough to justify a vacuum workflow?
- Which findings should fail CI or deployment checks?
- Which safe maintenance action should be run next?
Doctor is a diagnostic and maintenance assistant. It is not a backup tool, does not replace recovery testing, and does not perform destructive compaction or source-file replacement.
Quick start¶
Run the default human-readable report:
Write a machine-readable report:
Fail CI when warnings or errors are present:
Verify all indexes up to the default cap:
Run the safe v1 fix catalog:
Command shape¶
| Option | Default | Description |
|---|---|---|
--format <markdown|json|table|csv> | markdown | Output format. Doctor v1 renders table and csv as Markdown. |
--checks <list> | all | Comma-separated category filter. |
--verify-index <name> | none | Verify one named index. May be repeated. |
--verify-indexes | false | Verify all indexes up to --max-index-verify. |
--max-index-verify <n> | 32 | Cap for --verify-indexes. |
--fail-on <error|warning|info> | error | Exit with code 2 when a finding at or above this severity exists. |
--include-recommendations[=true|false] | true | Include or suppress recommendation text and commands. |
--path-mode <absolute|basename|redacted> | absolute | Controls how paths appear in reports. |
--fix | false | Run the constrained v1 fix catalog and report before/after state. |
Category names accepted by --checks are:
Use all to run every available category:
Run only WAL and index checks:
Exit codes¶
| Exit code | Meaning |
|---|---|
0 | Command completed and no finding met the --fail-on threshold. |
1 | Command-line parsing or report rendering failed. |
2 | Doctor completed, but at least one finding met the --fail-on threshold. |
The default threshold is error, so warning and info findings do not fail the command unless you choose a stricter threshold.
Examples:
# Only fail on errors.
decentdb doctor --db app.ddb --fail-on error
# Fail on warnings and errors.
decentdb doctor --db app.ddb --fail-on warning
# Fail on any finding, including informational findings.
decentdb doctor --db app.ddb --fail-on info
Report status and severity¶
Doctor findings use three severities:
| Severity | Report status effect | Typical meaning |
|---|---|---|
error | status: "error" | The database cannot be inspected fully, an index verification failed, or a fix action failed. |
warning | status: "warning" | Maintenance is recommended, such as checkpointing a large WAL or rebuilding a stale index. |
info | status: "ok" when no warnings/errors exist | Informational state or non-urgent advice. |
Findings are sorted deterministically by severity, category, and finding ID, so JSON reports are stable enough for automation and diffing.
Markdown output¶
Markdown is the default output and is intended for terminals, support tickets, and human review:
The report contains:
- Overall status.
- Database summary.
- Severity summary.
- Fix records when
--fixis used. - Findings with evidence and recommendations.
Example shape:
# DecentDB Doctor Report
## Status
Overall status: WARNING
## Database
| Field | Value |
|---|---|
| Path | app.ddb |
| Format version | 10 |
| Page size | 4096 |
| Page count | 128 |
| Schema cookie | 4 |
## Summary
| Severity | Count |
|---|---:|
| Error | 0 |
| Warning | 1 |
| Info | 1 |
JSON output¶
Use JSON when another tool needs to parse Doctor results:
Top-level fields:
| Field | Description |
|---|---|
schema_version | Doctor report schema version. v1 reports use 1. |
mode | check or fix. |
status | ok, warning, or error. |
database | Database path, WAL path, format version, page size, page count, and schema cookie. |
summary | Finding counts, highest severity, and checked categories. |
pre_fix_findings | Findings observed before --fix actions. Empty in check mode. |
findings | Current findings after checks, or after fixes in fix mode. |
fixes | Planned/applied/skipped/failed fix records. Empty in check mode. |
collected | Stable facts collected from engine metadata, including verified-index records. |
Minimal example:
{
"schema_version": 1,
"mode": "check",
"status": "warning",
"database": {
"path": "app.ddb",
"wal_path": "app.ddb.wal",
"format_version": 10,
"page_size": 4096,
"page_count": 128,
"schema_cookie": 4
},
"summary": {
"info_count": 1,
"warning_count": 1,
"error_count": 0,
"highest_severity": "warning",
"checked_categories": ["header", "storage", "wal", "fragmentation", "schema", "statistics", "indexes", "compatibility"]
},
"pre_fix_findings": [],
"findings": [],
"fixes": [],
"collected": {
"storage": {},
"header": {},
"schema": {},
"indexes_verified": []
}
}
Using Doctor in CI¶
For CI, prefer JSON plus an explicit --fail-on threshold:
A common policy is:
- Development smoke checks:
--fail-on error - Release gates:
--fail-on warning - Strict observability baselines:
--fail-on info
When paths in CI logs should not expose workspace or tenant names, combine JSON with --path-mode basename or --path-mode redacted:
decentdb doctor \
--db /var/lib/my-app/customer-123/app.ddb \
--format json \
--path-mode redacted \
--fail-on warning
Path rendering modes¶
--path-mode controls paths in the report:
| Mode | Behavior |
|---|---|
absolute | Render the path exactly as provided. |
basename | Render only file names, such as app.ddb and app.ddb.wal. |
redacted | Render <redacted> for database and WAL paths. |
Use basename for local logs where the file name is helpful but the full directory is not. Use redacted for multi-tenant logs, support bundles, or any environment where paths may contain customer identifiers.
Recommendations¶
By default, findings include safe recommendation text and, when useful, command snippets:
Suppress recommendations when a machine consumer only needs finding IDs, severities, and evidence:
Suppressing recommendations does not suppress findings, evidence, fixes, or exit-code behavior.
Index verification¶
Normal Doctor runs use metadata and do not perform a full logical scan of every index. Add index verification when you need stronger index-integrity evidence.
Verify one index:
Verify several indexes:
Verify all indexes up to the default cap:
Raise the cap for large schemas:
When the all-index request exceeds the cap, Doctor reports index.verify_skipped_limit and verifies only the capped subset. This prevents a surprise full-schema verification from turning a quick health check into a long maintenance job.
Verified index summaries appear in JSON under:
{
"collected": {
"indexes_verified": [
{
"index": "users_email_idx",
"expected_entries": 1000,
"actual_entries": 1000
}
]
}
}
If verification fails, Doctor emits an index.verify_failed error with expected and actual entry counts. In --fix mode, this finding is eligible for fix.rebuild_invalid_index.
Fix mode¶
Doctor is read-only unless --fix is provided:
Fix mode follows this sequence:
- Collect facts and run selected checks.
- Store the initial findings in
pre_fix_findings. - Plan only v1-supported fix actions.
- Execute the planned fix actions.
- Re-collect facts and re-run selected checks.
- Store current findings in
findings. - Store every planned/applied/skipped/failed action in
fixes.
Fix records use these statuses:
| Status | Meaning |
|---|---|
planned | The action was selected before execution. Final reports should normally show a terminal status instead. |
applied | The fix action completed. |
skipped | Doctor deliberately did not run the action, usually because a safety condition was not met. |
failed | The action returned an error. Doctor also emits a fix.failed error finding. |
Auto-fixable findings in v1¶
| Finding | Fix action | Behavior |
|---|---|---|
wal.large_file | fix.checkpoint | Runs a checkpoint when no active readers are present. |
schema.index_not_fresh | fix.rebuild_stale_index | Rebuilds the stale index named in finding evidence. |
index.verify_failed | fix.rebuild_invalid_index | Rebuilds the invalid index named in verification evidence. |
Doctor does not auto-vacuum fragmented databases. The safe vacuum workflow writes a separate output database, so Doctor recommends an explicit command instead:
Doctor also does not replace the source database, delete files, rewrite the file format, or run unsafe compaction.
Recommended fix workflow¶
For production databases:
- Take or verify a backup using your normal backup process.
- Run Doctor without fixes and save the report.
- Review the findings and planned safe actions.
- Run Doctor with
--fix. - Run Doctor again without
--fixand compare the report.
Example:
decentdb doctor --db app.ddb --format json > before.json
decentdb doctor --db app.ddb --fix --format json > fixed.json
decentdb doctor --db app.ddb --format json --fail-on warning > after.json
Common findings¶
| Finding ID | Severity | Meaning | Typical action |
|---|---|---|---|
header.unreadable | error | The file header cannot be read. | Check path, permissions, and file type. |
database.open_failed | error | Header was readable, but the engine could not fully open the database. | Use decentdb info, migration tooling, or a compatible engine version. |
compatibility.format_version_unknown | warning | Header format differs from the current engine format but opened successfully. | Confirm the expected engine version. |
wal.large_file | warning | WAL size exceeds the configured v1 threshold. | Checkpoint when readers are not holding snapshots; --fix may do this safely. |
wal.many_versions | warning | Many page versions are retained in the WAL. | Look for long readers or checkpoint starvation. |
wal.long_readers_present | warning | Active readers are holding WAL space. | Close long readers before checkpoint-sensitive operations. |
wal.reader_warnings_recorded | warning | Reader warnings have been recorded. | Inspect read transaction lifetime. |
wal.shared_enabled | info | Shared WAL mode is enabled. | Usually informational. |
fragmentation.high | warning | Free-list pages are high relative to total pages. | Consider decentdb vacuum --db <path> --output <new-path>. |
fragmentation.moderate | info | Some reusable free-list space exists. | Monitor; vacuum only if file size matters. |
schema.no_user_tables | info | No persistent user tables were found. | Usually expected for new databases. |
schema.many_indexes_on_table | info | A table has many indexes. | Review write overhead and query patterns. |
schema.index_not_fresh | warning | Index metadata says the index is stale. | Rebuild the index; --fix may do this safely. |
index.verify_skipped_limit | info | --verify-indexes exceeded the verification cap. | Verify specific indexes or raise --max-index-verify. |
index.verify_failed | error | Logical index entry count differs from table expectations. | Rebuild the index; --fix may do this safely. |
index.verify_error | error | Verification could not run for the index. | Check the index name and database state. |
fix.failed | error | A requested fix action failed. | Review the fix record and rerun Doctor without --fix. |
Troubleshooting¶
Doctor exits with code 2¶
Exit code 2 means Doctor completed and found something at or above your --fail-on threshold. Inspect findings in JSON or the Findings section in Markdown. Lower the threshold only if your policy allows it:
A large WAL finding remains after --fix¶
fix.checkpoint is skipped when active readers are present. Close long-running readers and rerun:
Index verification takes longer than a normal Doctor run¶
Index verification is opt-in because it performs stronger logical checks than metadata-only diagnostics. Use named verification for targeted checks:
The report hides paths¶
Check --path-mode. basename intentionally removes parent directories and redacted intentionally replaces paths with <redacted>.
Recommendations are missing¶
Check whether the command used:
When disabled, findings and evidence remain present but recommendation text and commands are omitted.