Handle missing or corrupt database on startup #22

Member

Adds async_open_database in __init_.py classifying three startup cases: file missing (SQLite creates fresh, migrations stamp v1), file valid (opens byte-identically, no-op path), file corrupt (ERROR log naming the path, ConfigEntryNotReady raised so HA retries, file left byte-identical for backup restore). Corruption matched on message spellings ('file is not a database', 'database disk image is malformed', 'encrypted or malformed') and classified from BOTH open() (truncated header fails at WAL PRAGMA) and migrations. Non-corruption failures also map to ConfigEntryNotReady with cause preserved. No code path deletes/overwrites the DB file (package-wide guard scan). 11 new tests incl. deliberately truncated file; suite 470 passed.

Adds _async_open_database in __init__.py classifying three startup cases: file missing (SQLite creates fresh, migrations stamp v1), file valid (opens byte-identically, no-op path), file corrupt (ERROR log naming the path, ConfigEntryNotReady raised so HA retries, file left byte-identical for backup restore). Corruption matched on message spellings ('file is not a database', 'database disk image is malformed', 'encrypted or malformed') and classified from BOTH open() (truncated header fails at WAL PRAGMA) and migrations. Non-corruption failures also map to ConfigEntryNotReady with __cause__ preserved. No code path deletes/overwrites the DB file (package-wide guard scan). 11 new tests incl. deliberately truncated file; suite 470 passed.
orchestrator-agent added 1 commit 2026-09-14 08:32:42 -04:00
overseer added 1 commit 2026-09-14 08:37:10 -04:00
- _preflight_existing_file probes an EXISTING file with a mode=ro URI
  connection before the read-write open, so a corrupt file is detected
  BEFORE WAL mode persists or sidecars appear; the preflight is inside
  the same ConfigEntryNotReady classification as open()/migrations
- corruption classification now prefers sqlite_errorcode (SQLITE_CORRUPT/
  SQLITE_NOTADB primary-byte match, locale-independent, Python 3.11+)
  with message fallback including 'database disk image is malformed'
- the early-return path (existing runtime record) routes through
  _async_open_database and reopens when db is None OR not connected
- new migration-stage corruption test: valid header + damaged page
  4096+, asserts main file byte-identical AND no -wal/-shm sidecars
  left behind; vacuous test replaced with pytest.raises form
overseer added 1 commit 2026-09-14 08:40:01 -04:00
- preflight now runs PRAGMA integrity_check (whole-file validation,
  not just sqlite_master) over a mode=ro connection, dispatched via
  hass.async_add_executor_job so the event loop never blocks
- migration-stage corruption test fixture is now a ROLLBACK-JOURNAL
  file created with plain sqlite3 (default journal mode), so the WAL
  transition the guardrail protects against actually happens in the
  test instead of being masked by an already-WAL fixture
overseer added 1 commit 2026-09-14 08:43:10 -04:00
- a non-ok integrity_check verdict raises DatabaseError carrying the
  NOTADB marker so it classifies as corruption unconditionally; ANY
  DatabaseError escaping the probe propagates (no more swallowing
  structural problems as non-corruption)
- file URI built via Path.resolve().as_uri() so #/?/% in paths cannot
  mis-target the probe
- migration-stage test now spies on NestQuestDatabase.open and asserts
  the read-write open was NEVER reached: the whole-file preflight
  rejecting corruption before the WAL transition is the mechanism
  under test, and the byte-identical + no-sidecar assertions prove it
- store guard permits SELECT + PRAGMA integrity_check on the ro-conn
overseer added 1 commit 2026-09-14 08:45:52 -04:00
- probe URI adds immutable=1: SQLite's documented guarantee that the
  read-only connection performs no writes and creates no -wal/-shm
  sidecars, even against a WAL-header database
- exists/stat/resolve and URI construction moved inside the executor
  job with the probe (no event-loop disk I/O)
- new WAL-header corruption test asserts byte-identical file and no
  -shm creation from the probe
orchestrator-agent merged commit 353f01e98c into feature/8940567d-7b50-41ef-a510-8b234fe7290e-sqlite-data-layer 2026-09-14 08:47:22 -04:00
Sign in to join this conversation.
No Reviewers
No labels
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Maniacs_Mansion/NestQuest#22