Skip to content

title: rledger check description: Validate beancount ledger files ​

rledger check ​

Validate a beancount ledger file for syntax errors and semantic issues.

Usage ​

bash
rledger check [OPTIONS] [FILE]

Arguments ​

ArgumentDescription
FILEThe beancount file to check (uses $RLEDGER_FILE or config if not specified)

Options ​

OptionDescription
-P, --profile <PROFILE>Use a profile from config (global flag)
--plugin-max-time-secs <SECS>Time budget for each WASM plugin call, overriding [plugins] max_time_secs (default: 30; global flag). See Plugin Time Budget
-v, --verboseShow verbose output including timing
-q, --quietSuppress all output (just use exit code)
-C, --no-cacheDisable the binary cache for parsed directives (also: BEANCOUNT_DISABLE_LOAD_CACHE=1)
-a, --autoImplicitly enable auto-plugins (auto_accounts, etc.)
--plugin <WASM_FILE>Load a WASM plugin (can be repeated)
--native-plugin <PLUGIN>Enable a native plugin (can be repeated)
-f, --format <FORMAT>Output format: text, json
--lint <NAME>Run non-fatal advisory lints alongside validation (can be repeated). Available: transfers
--lint-min-confidence <VALUE>Minimum confidence (0.0 - 1.0) for --lint transfers matches to be reported (default: 0.8)
--show-summaryPrint a count of diagnostics per rule code, most frequent first
--include-rules <CODES>Report only these rule codes (comma-separated, e.g. E2001,E1001)
--exclude-rules <CODES>Report everything except these rule codes (comma-separated)

Examples ​

Basic Validation ​

bash
rledger check ledger.beancount

Output on success:

✓ No errors found

Output with errors:

error[E3001]: Transaction does not balance
  --> ledger.beancount:42:1
   |
42 | 2024-01-15 * "Coffee shop"
   | ^^^^^^^^^^^^^^^^^^^^^^^^^
   = help: Expenses:Food has 5.00 USD, Assets:Bank has -4.99 USD
   = note: residual: 0.01 USD

✗ 1 error

Triaging a Long List ​

A ledger part-way through an import can produce a lot of findings at once. --show-summary says what they are before you start scrolling:

bash
rledger check main.beancount --show-summary
Summary (37 total):
  31  E2001
   4  E1001
   2  E3001

Then work one rule at a time:

bash
# just the balance assertions
rledger check main.beancount --include-rules E2001

# everything except them, when the history is not imported yet
rledger check main.beancount --exclude-rules E2001

Codes are case-insensitive, and --exclude-rules wins over --include-rules for a code named in both. If --include-rules matches none of the diagnostics found — usually a mistyped code — check says so and lists the codes that were present, rather than leaving an error count with nothing under it:

✗ 3 errors

note: --include-rules matched none of the diagnostics found. Present: E1001, E2001

Filtering changes only what is displayed. The exit code still reflects every error found, so a --exclude-rules run that prints nothing still fails if the ledger has errors — hiding a diagnostic must not turn a failing check into a passing one in CI. That holds for parse errors too: excluding a P code does not make a file that cannot be parsed report success. For the same reason, --show-summary counts what was found, not what survived the filter, and says so when a filter is active.

With --format json, --show-summary adds a rule_summary object instead of printing a table:

json
{ "diagnostics": [ ... ], "error_count": 3, "rule_summary": { "E2001": 2, "E1001": 1 } }

The field is absent unless the flag is given.

With Plugins ​

bash
# Enable specific plugins
rledger check --native-plugin auto_accounts --native-plugin implicit_prices ledger.beancount

# Plugins declared in the file are auto-detected
# plugin "beancount.plugins.auto_accounts"  <- uses native implementation

JSON Output ​

bash
rledger check -f json ledger.beancount
json
{
  "diagnostics": [
    {
      "file": "ledger.beancount",
      "line": 42,
      "column": 1,
      "end_line": 42,
      "end_column": 26,
      "severity": "error",
      "phase": "validate",
      "code": "E3001",
      "message": "Transaction does not balance",
      "hint": "Expenses:Food has 5.00 USD, Assets:Bank has -4.99 USD"
    }
  ],
  "error_count": 1,
  "warning_count": 0,
  "parse_error_count": 0,
  "validate_error_count": 1
}

Using Environment Variable ​

bash
export RLEDGER_FILE="$HOME/finances/main.beancount"
rledger check  # uses $RLEDGER_FILE

Cache File ​

To make subsequent runs near-instant, rledger check writes a binary snapshot of the parsed ledger next to the source file as a hidden dotfile:

ledger.beancount         → .ledger.beancount.cache
finances/main.beancount  → finances/.main.beancount.cache

The cache is invalidated automatically when any source file (the main ledger or anything it includes) changes. Invalidation is based on each file's path, modification time, and size — if any of those differ from when the cache was written, the cache is rejected and the ledger is re-parsed.

Controlling the cache ​

MechanismEffect
--no-cache / -C flagDisable for one invocation
BEANCOUNT_DISABLE_LOAD_CACHE=1Disable persistently (env)
BEANCOUNT_LOAD_CACHE_FILENAME=<pattern>Redirect to a custom path

The BEANCOUNT_LOAD_CACHE_FILENAME pattern may contain {filename} (replaced with the source basename). Relative paths resolve against the source file's directory; absolute paths are used as-is.

bash
# All caches in ~/.cache/rledger/, named after the source file
export BEANCOUNT_LOAD_CACHE_FILENAME="$HOME/.cache/rledger/{filename}.cache"

These environment variable names match Python beancount, so existing bean-check muscle memory works unchanged.

Migration from earlier rustledger versions ​

Versions before this fix (issue #939) wrote the cache as a visible file (ledger.beancount.cache). Upgrading will silently delete the old visible file the first time rledger check writes a new cache for that ledger. No action required; if you've added *.beancount.cache to .gitignore you can safely remove the entry.

Error Codes ​

Common validation errors:

CodeDescription
E1001Account not opened
E1002Account already opened
E2001Balance assertion failed
E2002Balance exceeds explicit tolerance
E3001Transaction does not balance
E3002Multiple postings missing amounts for same currency

See Error Reference for all error codes.

See Also ​