Skip to content

[BUG] A new choice is discarded if any settings write lands while its builder is open #1625

Description

@chhoumann

Found while fixing #1608, deliberately not grown into that PR: it is on master today, independent of the id repair, and it is data loss on the happy path rather than the malformed one.

The shape

ChoiceView.addChoiceToList adds the new choice to the LOCAL tree and then hands off to the builder without saving first (ChoiceView.svelte, the else if (!skipConfigure) arm):

choices = addChoiceToTree(choices, newChoice, targetFolderId);
...
// Doers hand off to their builder, which both names and configures the
// choice and persists the result - no eager save (avoids a double write).
await handleConfigureChoice(newChoice);

Meanwhile the view subscribes to settingsStore unfiltered and re-seeds the whole tree on every emission:

settingsStore.subscribe((settings) => {
    choices = seedChoices(settings.choices);   // was: choices = settings.choices
    ...
});

The store does not know about newChoice yet - nothing saved it. So any emission that lands while the builder is open replaces the local tree with one that does not contain it, and the builder's own save then persists a tree without the choice the user just spent a minute configuring.

Why it is reachable without the user doing anything

autoSyncEnabledProviders (main.ts, inside onLayoutReady) calls settingsStore.setState from modelSyncService.ts:109 a few seconds after launch. Several migrations do too. Open the settings tab quickly after starting Obsidian, click "New choice", and the window is real.

The same window applies to handleRenameChoice and to anything else that mutates the local tree and awaits before saving.

Suggested shape

Two options:

  1. Save before handing off. It costs the double write the comment is avoiding, but the comment is trading a write for a data-loss window.
  2. Make the subscription non-clobbering: ignore an emission whose choices is reference-identical to what this view last SENT, and otherwise reconcile rather than replace. The seam added in [BUG] Reordering the choice list deletes any choice the render filter dropped #1608 already memoizes on the raw reference, so the hook is there.

(1) is smaller and obviously correct; (2) is the real fix if there are other await-then-save paths.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions