Diagnostics
Every run returns a DiagnosticReport alongside the snapshot. Read the report when a run came back smaller than expected; it tells you why without poking at engine internals.
DiagnosticReport
pub struct DiagnosticReport {
pub stall_reason: Option<RuntimeDiagnostic>,
pub unmet_expectations: Vec<RuntimeDiagnostic>,
}
pub struct RuntimeDiagnostic {
pub message: String,
pub line: Option<u32>, // 0-based source line, when resolvable
}stall_reason
Present only when a successful run was cut short — it flags that the snapshot may be incomplete. A clean run leaves it absent: an empty report is the "ran to completion" signal (forage test keys its exit code off that). Hard failures don't land here — a failed HTTP request, a visit with no recorded capture, or an expression that threw end the run with an error, not a stall.
The message is free-form, not a fixed tag. The cases today:
message | When |
|---|---|
visit '<name>' hit maxIterations (<n>) before settling; the capture may be incomplete | A visit's scroll / click loop ran its maxIterations cap without the page going quiet. |
visit '<name>' ran out of time before settling; the capture may be incomplete | A visit exceeded its time budget without the page going quiet. |
output capped at sample limit <n> (<m> available); this is a sampled subset | sample_limit trimmed a top-level for, so the snapshot is a deliberate subset. |
The first stall wins: a run with several truncation points reports the earliest.
unmet_expectations
One RuntimeDiagnostic per failing expect { … } clause, its message a pre-rendered description and its line the clause's source line. See the expectations page for syntax and rendering.
records.where(typeName == "Product").count >= 500 (got 247)Reading a report
forage run prints the report's non-empty sections after the snapshot:
- Unmet expectations → the recipe ran but produced less than the
expectclauses demand. When avisitis involved, this usually means it didn't reach all the data: the page needs morescroll/clickiterations before it settles, or amatched("…")pattern points at the wrong endpoint. - Stall reason → the run finished but was cut short: a
visitgave up before settling, orsample_limittrimmed the output. The message carries the specifics. (An outright failure — bad HTTP status, missing replay capture, a throwing expression — surfaces as a run error instead, not in the report.)
In Studio, the Diagnostic tab renders each section as a list; click a row to jump to the relevant span in the editor.
Persisting reports
The diagnostic is part of the Snapshot that forage test diffs against _snapshots/<recipe>.json. Re-reading a snapshot lets you diff today's report against last week's without rerunning the engine.