Troubleshooting
Organized by surface. The CLI prints a diagnostic as its severity and code, the message, then the file, line and column, and the hint when there is one:
error[E4004_MISSING_PACK]: Pack 'retail' was not found in the packs built into this binary.
--> my-model/model.cfdl:3:1
= hint: Add a matching pack manifest or pass --packs <dir>.Every code is cataloged in the Diagnostics reference.
CLI
-
use packfails to resolve (E4004_MISSING_PACK) — the named pack is not among the packs the command reads:--packs <dir>, apacks/directory in the working directory, or the four built into the binary. Check the pack's name and version inuse pack, and what a directory holds withcfdl pack list --path <dir>. -
--packsis refused (E4004_MISSING_PACK) — the path does not exist, or no folder under it has apack.toml:error[E4004_MISSING_PACK]: The pack directory './pakcs' does not exist. = hint: Pass the folder that holds the pack folders (each with a pack.toml), or leave --packs out to use ./packs or the packs built into cfdl. = note: pack root: ./pakcs -
Domain metrics missing from results —
cfdl runneeds--pack <name>(e.g.--pack cre) to apply a pack's metric set. -
No
model.npvin the results — no discount rate reached the run, so the run publishes no NPV rather than one at a rate nobody chose. Pass--rate, or setdeterministic.annual_discount_rateorannual_discount_curvein the run configuration. -
A run configuration key is refused (
E5033_INVALID_RUN_CONFIG) — a key matches nothing the model declares or reads, or a setting is malformed. The message names the nearest name:cprforinputs.cpr, a misspelled assumption, or the retiredstream.<name>:amount.error[E5033_INVALID_RUN_CONFIG]: Failed to load run config 'run.json': invalid run config: valuation_grain 'weekly' is not a grain this engine knows; use "annual", or omit it for the model's own grain --> run.json = hint: Ensure run.json is valid JSON and matches run config schema. -
Machine-readable errors — add the global
--jsonflag; diagnostics come out structured with their codes.
Compile errors (any surface)
-
Missing required model header (
E1101,E1102,E1103) — every model needsversion,modelandtimeexactly once.error[E1101_MISSING_VERSION]: Model is missing required 'version' statement. --> model.cfdl:1:1 -
No entity (
E1109_MISSING_ENTITY) — every stream belongs to an entity, so a model declares at least one.error[E1109_MISSING_ENTITY]: Model must declare at least one entity. --> model.cfdl:1:1 -
Unresolved entity refs (
E1301) — theentitymust exist, and a reference names its family and name,asset.tower.error[E1301_UNRESOLVED_ENTITY_REF]: Event 'refi' references unknown entity 'asset.ghost'. --> model.cfdl:28:1 -
Import failures — import paths are relative to the importing file; no cycles; imports cannot escape the model root.
error[E1201_IMPORT_CYCLE]: Import cycle detected: 'b.cfdl' depends on 'a.cfdl' through a cycle. --> b.cfdl:1:1 = related: a.cfdl:1:1 'a.cfdl' imports 'b.cfdl' here. = related: b.cfdl:1:1 'b.cfdl' imports 'a.cfdl' here. error[E1203_IMPORT_OUTSIDE_MODEL_ROOT]: Import path '../outside.cfdl' escapes the model root. --> model.cfdl:4:1 -
Pack term validation — the pack's required terms must be present with the right shapes; see each pack guide's term table. Missing-term and unknown-term diagnostics name the term.
error[E1372_MISSING_CONTRACT_TERM]: Contract 'cre.lease' states none of rent, rent_year, rent_psf, rent_per_unit_month; type 'CRE.Contract.AggregateLease' requires one of them. --> model.cfdl:22:1 -
Schedule range issues (
E2103) —from <= to, and dates must land inside the model timeline.error[E2103_SCHEDULE_OUT_OF_BOUNDS]: Stream 'debt.principal' schedule is outside model timeline (timeline: 2026-01-01 to 2026-12-01). --> model.cfdl:7:12 -
A schedule finer than the calendar (
E2108_SCHEDULE_FINER_THAN_CALENDAR) —every weekon a monthly timeline cannot be told apart once it lands in one period. Make the timeline as fine as the finest schedule.error[E2108_SCHEDULE_FINER_THAN_CALENDAR]: Stream 'co.rent' pays every week but the model's calendar is monthly. Occurrences inside one period share that period's environment and cannot be told apart, so an amount that varies over time would be computed once and multiplied. Use an interval of monthly or longer, or declare a finer calendar. --> model.cfdl:11:12 -
prev.in the first period (E1129_PREV_IN_FIRST_PERIOD) — a stream reads a field's previous period but runs from the model's first period, where there is none. Start the schedule one period later, or guard it.error[E1129_PREV_IN_FIRST_PERIOD]: Stream 'opco.interest' reads a field's previous period but runs from the model's first period, where there is none. Start the stream one period later, or carry the opening value as a field of its own. --> model.cfdl:25:3 = hint: A field's previous period is the close before this one; the first period has no close before it. -
A series or quantile read the wrong way (
E2312_ASSUME_SHAPE_READ) — a quantile read bare, a series in an entity's=field, or a name passed as a string,curve_value("sofr", …). Read a series asinputs.sofrorcurve_value(inputs.sofr, <date>), and a quantile throughquantile_at,quantile_meanorquantile_of.error[E2312_ASSUME_SHAPE_READ]: `streams[0].amount` reads `inputs.prices` bare, and `prices` is a quantile. A quantile function has no single value. --> model.cfdl:12:1 = at: streams[0].amount = hint: Read a slice of it: `quantile_at(inputs.prices, <share>)`, `quantile_mean(inputs.prices, <from>, <to>)` or `quantile_of(inputs.prices, <value>)`. -
A cash stream with no category (
E5029_STREAM_MISSING_CATEGORY) — while a pack is active, everyinfloworoutflowstream states acategoryfrom the pack's vocabulary, so the pack's subtotals and domain metrics count it.error[E5029_STREAM_MISSING_CATEGORY]: Stream 'misc.windfall' declares no category, and pack 'cre' is active. Its cash would reach model.total and fold into no subtotal — invisible to every domain metric, silently. --> model.cfdl:11:1 = hint: State what the flow IS, as a path into the cash flow statement: `category operating.revenue.rent`, `category financing.debt.interest_paid`. A category is only optional when no pack is active, because then nothing folds.
Run errors
-
A name nothing binds (
E5031_UNRESOLVED_NAME) — a run read a name that resolves to nothing: a mistypedinputs., or a bare assumption name written withoutinputs.. The run is refused, naming every such name, rather than read as zero.error[E5031_UNRESOLVED_NAME]: Run failed on IR 'ir.json': unresolved name: `cfg.rate` is not declared — declare it, supply it in the run configuration, or correct the name — each read as zero. --> ir.json -
An expression failed (
E5043_EXPRESSION_EVALUATION_FAILED) — a division by zero, a function argument out of range, or a non-numeric result, in an amount, a guard, a condition or a waterfall step. The run is refused rather than given a value.error[E5043_EXPRESSION_EVALUATION_FAILED]: Run failed on IR 'ir.json': Stream 'co.fee' amount at period 2 failed [EXPR_EVAL]: division by zero — a value that was never computed is not a number, and a condition that could not be evaluated did not hold or fail. Guard the expression for the period it fails in, or correct it. --> ir.json
Monte Carlo
monte_carlo.status: "not_run"— neither the model nor the run configuration asked for trials. A model statesrun monte_carlo trials <n> seed <s>, or the run configuration states"monte_carlo": { "trial_count": N, "seed": S }; when both do, the configuration wins.- Results differ between machines — they should not: runs are
byte-reproducible given the same release. Confirm the same version
(results carry
engine.versionandmodel_hash) and the same seed.
VS Code
- No diagnostics/hover — verify
cfdl.serverPathpoints at the rightcfdl-lspbinary and that it is executable; setcfdl.trace.server = "verbose"to inspect client/server traffic. - Pack diagnostics wrong in the editor —
cfdl.packsPathmust point to the same packs directory you compile with. - Full setup: VS Code and LSP.
Python SDK
CompileError/RunError— both carry structured details (CompileError.diagnosticshas codes and spans; do not parse the string form).- A pack-bearing model refuses with
E4004— the named pack is neither among the four built into the package nor in thepacks_dirpassed. Check the pack's name and version inuse pack, and the path. See Install for Python.
API server
- HTTP 413 — request body over 1 MiB. 408/timeout — 10 s cap. 400 on Monte Carlo — trial count above the server cap (1000); it is rejected, never silently truncated.
- 422 with a diagnostics body — same compile/validate errors as the CLI, structured.
Playground
- A model of several files is written with the New file dialog and
import. Long Monte Carlo runs are limited by the browser tab; when you hit a wall, move to the CLI.