A state file holding {} crashes the watcher on its first check #267

Closed
opened 2026-10-13 12:32:08 +02:00 by clawbot · 0 comments
Collaborator

What is wrong. Load accepts any JSON object. A state file without the domains, hostnames, ports and certificates sections loads with nil maps, and the first SetDomainState (or SetHostnameState, SetPortState, SetCertificateState) panics with assignment to entry in nil map. The panic is in the watcher goroutine, so the process dies, and dies again at every restart until the file is fixed.

Where (at e8b4006): internal/state/state.go, Load lines 210-230 (s.snapshot = &snapshot with whatever maps the file had); SetDomainState line 289 and the other setters assign into them.

Scenario. An operator resets the state by writing {} or {"version": 1} to state.json, or hand-edits the file and drops a section (the trial run in #260 edits it between restarts). Confirmed: loading a file holding {} and then calling SetDomainState panics with assignment to entry in nil map.

Correct. A state file with a missing section loads as if the section were empty, as a missing file loads as empty state (README, Monitoring Lifecycle: "If no state file exists, start with empty state"). Load fills in each nil map after parsing.

Done when: loading {}, and a file missing any one section, gives an empty map for each missing section and the first check runs; a test covers both.

Severity: minor

Model: fable-5-1

**What is wrong.** `Load` accepts any JSON object. A state file without the `domains`, `hostnames`, `ports` and `certificates` sections loads with nil maps, and the first `SetDomainState` (or `SetHostnameState`, `SetPortState`, `SetCertificateState`) panics with `assignment to entry in nil map`. The panic is in the watcher goroutine, so the process dies, and dies again at every restart until the file is fixed. **Where** (at `e8b4006`): `internal/state/state.go`, `Load` lines 210-230 (`s.snapshot = &snapshot` with whatever maps the file had); `SetDomainState` line 289 and the other setters assign into them. **Scenario.** An operator resets the state by writing `{}` or `{"version": 1}` to `state.json`, or hand-edits the file and drops a section (the trial run in https://git.eeqj.de/sneak/dnswatcher/issues/260 edits it between restarts). Confirmed: loading a file holding `{}` and then calling `SetDomainState` panics with `assignment to entry in nil map`. **Correct.** A state file with a missing section loads as if the section were empty, as a missing file loads as empty state (README, Monitoring Lifecycle: "If no state file exists, start with empty state"). `Load` fills in each nil map after parsing. **Done when:** loading `{}`, and a file missing any one section, gives an empty map for each missing section and the first check runs; a test covers both. Severity: minor Model: fable-5-1
clawbot added this to the 1.0 milestone 2026-10-13 12:32:08 +02:00
clawbot self-assigned this 2026-10-13 12:32:08 +02:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/dnswatcher#267