Troubleshooting the deadline app
At a glance
Section titled “At a glance”-
Goal: match each failure you will actually meet to its cause and its fix, without guessing.
-
You need: any chapter — this page is the escape hatch every other chapter points to. Read the failing line first, then the symptom row, then run the chapter’s check again.
-
Run: the two diagnostic commands most rows lead to — is the question executable, and what does the draft still miss:
Terminal node --import tsx src/cli.ts check-contractnode --import tsx src/cli.ts explain --candidate 2026-03-20 --event 2026-03-06 -
Files: most fixes land in the adapter or the queries:
Output src/to-case.ts MODEL_SPEC, fact predicates and unitssrc/query.ts question names and argument shapes
Diagnose in order
Section titled “Diagnose in order”Read failures outside in: first the thrown error (the application
failed before any answer existed), then evaluationStatus (the engine
declined), then truthStatus and values (the engine answered, and the
answer may be inconclusive). Each layer has its own fix, and skipping
a layer mislabels the fault — most often by reading a declined
evaluation as a wrong value.
Symptoms
Section titled “Symptoms”| Symptom | Cause | Fix |
|---|---|---|
PackageNotFound on open | canon package not installed, or the spec names a version that is not there | npm ci; confirm MODEL_SPEC is de.bgb.fristen@0.1.0 and the installed canon package is 0.1.5 |
FactError with nearest: [...] | a predicate name the canon does not know — misspelt, or renamed by a model change | pick the intended name from nearest; fix it in to-case (facts) or query (questions) |
NEITHER on every question | missing facts, an underived-but-declared claim, or a wrong candidate (an undeclared predicate raises FactError instead — see the row above) | first check-contract confirms the questions are executable, then explain on the draft: the ask list names the missing fields |
collect answers COMPUTED with no values | the rules derived nothing for these facts — usually a missing premise | same as above: explain on the matching draft names the gap; do not render “no value” as an end date |
sources: [] on every answer | this canon build attaches no source anchors to answers | expected on this build: show the applied rule identifier as the address and state the empty list plainly |
| hash mismatch replaying a good capture | bytes compared across SDKs, a case or query edit, or a spec mismatch | replay with the same SDK that saved the capture; read the replay detail — it distinguishes mismatch from refusal from an integrity failure |
replay refused: capture model … ≠ replay model … | the capture was saved under another spec | replay against the recorded spec, not the open one; versions are never mixed |
address already in use on npm start | the port is busy, usually a previous server still running | stop the previous server, or PORT=8788 npm start; HOST overrides the loopback bind |
tsx: command not found | the TypeScript runner is not installed | npm ci installs the pinned toolchain; the suite needs it too |
| type error on a predicate argument | a value that does not match the declared parameter type — a date where the canon wants a quantity, or a misspelt unit | read the parameter list from questions('en') and fix the adapter; '14 calendar_day' needs the exact unit name |
not-computed on a previously fine case | the call now declines: a reading must be chosen, or a question needs a decision the engine will not make | the view shows the status (Not computed: …); treat it as a prompt for input, not as a crash |
| checksum mismatch on the download | a corrupt or substituted archive | re-download; do not proceed past a failed shasum -c |
Two symptoms newcomers misread
Section titled “Two symptoms newcomers misread”Two rows deserve emphasis because newcomers misread them most. NEITHER
everywhere feels like the engine is broken; it means neither the claim
nor its negation is supported. Missing facts are one possible cause,
not the only one — full input also answers NEITHER on a wrong
candidate date. Check the query against the model first (an unknown
relation is an integration error, not a NEITHER), then investigate
the blockers: run explain before changing anything — on the partial
example case it asks for durationDays and reports the computed
intermediate as not askable.
The hash mismatch row feels like corruption; across SDKs it is normal.
TypeScript and Python return the same statuses and the same values on
the same case, but their canonical bytes differ, so their result
hashes differ too. Same-SDK comparison is the rule; the capture format
records enough (adapter, model, versions) to enforce it.
Limits and errors
Section titled “Limits and errors”- This table covers the application’s failures, not the canon’s content: if the rules compute a date you believe the provisions do not support, that is a question for the canon author, with the rule identifier and the capture attached.
- Python has no
questions, nounfold, and nofocused_truth. A PythonAttributeErroron one of those names is not a bug in your code — read the manifest from the TypeScript SDK instead. - A document-checksum failure on a capture has no fix except discarding the file. Re-export from the case that produced it.
Check your understanding
Section titled “Check your understanding”Break one thing on purpose, watch the expected failure, then restore it.
Stage 1 — break the adapter. In src/to-case.ts, delete the
frist_dauer_tage line from toFacts (leave toDraftFacts as it
is), then run the missing-facts tests:
node --import tsx --test test/missing.test.tsExactly one test fails — the complete form now sends no duration, so
the questionnaire asks for durationDays again instead of stopping on
NEITHER:
not ok 5 - a complete case with a wrong candidate ends the questionnaire on NEITHER expected: 'none-askable' actual: 'ask'# tests 14# pass 13# fail 1Stage 2 — restore the line and run the same command again. The suite is green:
ok 1 - a draft with only the event asks for durationDaysok 2 - an empty draft asks for both fieldsok 5 - a complete case with a wrong candidate ends the questionnaire on NEITHER# tests 14# pass 14# fail 0If stage 1 shows no failure, the tests are not running against your edit — check the working tree before trusting any green line.
Predict before you open each answer.
In stage 1, why do the draft tests 1–4 still pass?
They build their facts with toDraftFacts, which still sends the
duration when the draft has one. Only test 5 builds a complete case
with toFacts, the function you edited.
Every question answers `NEITHER` on a fully filled form. What do you run first?
check-contract, to confirm the questions are executable — an
unknown predicate would raise FactError, not NEITHER. Then
explain on the draft. A full form with a wrong candidate date also
answers NEITHER, so missing facts are only one possible cause.
- Build with Arxo: route map
- Quickstart to revisit the single-file version
- How to read an answer
- Connect an AI assistant
Documentation for Arxo. Writings — blog.arxo.io.
Anonymous visit counts on stats.arxo.io, no cookies.