config-merge: a malformed config file silently reverts all settings to defaults (indistinguishable from absent) #39
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#39
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: config · surfaced in the post-v1.2.0 cross-model review sweep. Independently flagged by two reviewers (highest-confidence finding of the sweep).
What happens
The shared config reader cannot distinguish an absent config layer from a malformed one — both collapse to a dropped layer with no signal. A syntax error in
.planning/config.json(a stray trailing comma, say) silently removes the entire repo config layer, and every setting reverts to its default: routing tier back tobalanced, git rails back to built-ins, memory backend back tobuiltin. The only trace is thesourcefield readingdefaults/globalinstead ofrepo— which no consumer treats as an error.Its most serious consequence chains into #38: a malformed config silently reverts the
git-guardsafety rail to defaults as well.Mechanism (verified against source)
cadence-core/bin/lib/config-merge.mjs:21-24: IO error (absent) andSyntaxError(malformed) both returnnull.mergeLayers(config-merge.mjs:47-57) pushes a layer name only when the layer is truthy, so a malformed repo layer is indistinguishable from a missing one; both yield the merged result of whatever remains, andsourcenever reflects that a layer failed to parse.Design note
The swallow is deliberate and defensible — "a bad layer is skipped, never fatal (the spine must not block on config)" — and this issue is not a request to make it fatal. The defect is the total silence: a broken config should be visible, not invisibly ignored.
Fix direction
Keep the fail-safe, but distinguish a parse failure from absence and surface it — e.g. a one-line stderr warning naming the file, and/or a distinguishable
sourcevalue such asdefaults (repo config failed to parse)— so the operator can tell "settings not applied because the file is broken" from "no repo config present."