Skip to content

fix(config,persist): Harden config validation and serialize session updates - #45

Merged
mhiro2 merged 4 commits into
mainfrom
fix/config-and-persist-hardening
Aug 27, 2026
Merged

fix(config,persist): Harden config validation and serialize session updates#45
mhiro2 merged 4 commits into
mainfrom
fix/config-and-persist-hardening

Conversation

@mhiro2

@mhiro2 mhiro2 commented Aug 27, 2026

Copy link
Copy Markdown
Owner

Summary

  • setup() no longer crashes on a top-level section replaced with a non-table value or on a misspelled autocmd event name, honoring the documented never-throws guarantee.
  • Persisted session updates are serialized so overlapping async save/delete/rename calls can no longer overwrite each other with a stale snapshot.
  • Malformed version 2 session entries are normalized when loading so a corrupt store cannot crash restore, save or rename.

Changes

  • ed875d8 : fix(config): restore top-level sections replaced with non-table values
    • setup({ ui = false }) now warns and falls back to the default ui section instead of leaving a boolean that crashed the first consumer indexing it; the same applies to picker, providers and persist.
  • afbe730 : fix(config): drop unknown autocmd event names from close_events
    • Each close_events entry is checked with vim.fn.exists("##<name>"); unknown names such as CursorMoveed are ignored with a warning instead of making nvim_create_autocmd() throw at setup time.
    • Falls back to the default event list when no valid entry remains.
  • 1675b5f : fix(persist): normalize malformed session entries when loading version 2 data
    • Non-table session entries are dropped, items is coerced to a list and meta to a record with numeric timestamps, so a hand-edited or partially written store no longer crashes restore/upsert/rename.
  • 2b0ef0e : fix(persist): serialize read-modify-write updates to prevent lost sessions
    • All mutations go through a queued update_async that starts each read only after the previous write completed, eliminating the read-modify-write lost update between concurrent save/delete/rename.
    • Sync saves (e.g. on VimLeavePre) drain in-flight async updates before writing, and a throwing on_done callback can no longer wedge the queue.

mhiro2 added 4 commits August 27, 2026 21:14
setup({ ui = false }) left cfg.ui as a boolean because field validators only
descend into tables, and the first consumer that indexed it crashed. Restore
such sections to their defaults with a warning so setup() keeps its
never-throws guarantee.
nvim_create_autocmd() throws on an event name it does not know, so a typo
such as "CursorMoveed" crashed setup(). Validate each entry with
vim.fn.exists("##<name>") and ignore unknown ones with a warning, falling
back to the defaults when nothing valid remains.
…n 2 data

migrate.ensure only checked that `sessions` was a table, so a hand-edited or
partially written store such as `sessions.bad = true` passed through and
crashed the first consumer that indexed it (restore, upsert, rename).

Drop entries that are not tables and coerce each remaining session into the
expected shape: `items` must be a list, `meta` must be a record with numeric
created_at/updated_at.
…sions

Async save/delete/rename each read the store, mutated their own snapshot and
wrote it back. When two of them overlapped, the last write to finish carried
a stale snapshot and silently discarded the other's change. Unique temp file
names only protected the write itself, not the read-modify-write sequence.

Route all mutations through orchestrator.update_async, which queues them and
starts each read only after the previous write completed. Callback errors are
caught so a throwing on_done cannot wedge the queue. The sync save path goes
through update_sync, which drains in-flight async updates (bounded wait)
before its own read-modify-write, so a save on VimLeavePre no longer races an
async save that is still mid-flight.
@mhiro2 mhiro2 self-assigned this Aug 27, 2026
@mhiro2 mhiro2 added the bug Something isn't working label Aug 27, 2026
@mhiro2
mhiro2 merged commit f00bf6c into main Aug 27, 2026
3 checks passed
@mhiro2
mhiro2 deleted the fix/config-and-persist-hardening branch August 27, 2026 13:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant