Skip to main content
CFDL

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 pack fails to resolve (E4004_MISSING_PACK) — the named pack is not among the packs the command reads: --packs <dir>, a packs/ directory in the working directory, or the four built into the binary. Check the pack's name and version in use pack, and what a directory holds with cfdl pack list --path <dir>.

  • --packs is refused (E4004_MISSING_PACK) — the path does not exist, or no folder under it has a pack.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 run needs --pack <name> (e.g. --pack cre) to apply a pack's metric set.

  • No model.npv in 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 set deterministic.annual_discount_rate or annual_discount_curve in 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: cpr for inputs.cpr, a misspelled assumption, or the retired stream.<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 --json flag; diagnostics come out structured with their codes.

Compile errors (any surface)

  • Missing required model header (E1101, E1102, E1103) — every model needs version, model and time exactly 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) — the entity must 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 week on 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 as inputs.sofr or curve_value(inputs.sofr, <date>), and a quantile through quantile_at, quantile_mean or quantile_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, every inflow or outflow stream states a category from 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 mistyped inputs., or a bare assumption name written without inputs.. 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 states run 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.version and model_hash) and the same seed.

VS Code

  • No diagnostics/hover — verify cfdl.serverPath points at the right cfdl-lsp binary and that it is executable; set cfdl.trace.server = "verbose" to inspect client/server traffic.
  • Pack diagnostics wrong in the editor — cfdl.packsPath must point to the same packs directory you compile with.
  • Full setup: VS Code and LSP.

Python SDK

  • CompileError / RunError — both carry structured details (CompileError.diagnostics has 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 the packs_dir passed. Check the pack's name and version in use 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.