route.mjs / config.mjs: top-level data-file parse runs outside the dispatch guard (raw crash instead of {ok:false}) #40
Labels
No labels
already-shipped
bug
documentation
duplicate
enhancement
good first issue
help wanted
in progress
invalid
needs-decision
proposal
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: crenshawdev/cadence#40
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Severity: medium · Area: seam-contract · surfaced in the post-v1.2.0 cross-model review sweep.
route.mjswas flagged by all three reviewers;config.mjsby one.What happens
route.mjsandconfig.mjsboth promise, in their header, to never crash the spine: on any problem they emit one JSON line{ok:false,...}so the caller degrades gracefully. But each parses its shipped data file at module top level, before the try/catch that guards command dispatch. A missing or malformed data file (partial install, bad edit, botched merge) therefore throws a rawSyntaxErrorwith no JSON on stdout — the caller parsing the single-JSON-line contract gets nothing.Mechanism (verified against source)
cadence-core/bin/route.mjs:32:const TABLE = JSON.parse(readFileSync(join(HERE, '..', 'route-table.json'), 'utf8'));at module load; the dispatch guard is further down. Contract stated atroute.mjs:9-10("Never blocks the spine: on any problem it returns {ok:false,...}").cadence-core/bin/config.mjs:30-32:const SCHEMA = JSON.parse(readFileSync(join(HERE, '..', 'config.schema.json'), 'utf8')).keys;at module load; the dispatchtrystarts atconfig.mjs:213.Trigger for both: the data file is absent or not valid JSON.
Fix direction
Move each top-level
JSON.parse(readFileSync(...))into (or behind) the command guard, so a bad data file degrades to the contracted{ok:false, reason, detail}line instead of an uncaught stack. A shared helper (load-or-fail returning the structured error) would cover both.Out of scope (intentionally)
self-verify.mjs:149loadsconfig.schema.jsonthe same way, but self-verify is a dev/CI tool where a loud crash on a corrupt shipped schema is acceptable; it makes no "never blocks the spine" promise. Left as-is by design.