{"record":{"id":"073d9847b276fe69","repo":"tonhowtf/omniget","slug":"setactive-failed","errorCode":null,"errorMessage":"setActive failed","messagePattern":"setActive failed","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/lib/study-notes/notebooks-store.svelte.ts","lineNumber":96,"sourceCode":"      console.warn(\"notebooksStore.refresh failed\", e);\n    }\n  }\n\n  pageCountOf(id: number): number {\n    return this.list.find((n) => n.id === id)?.page_count ?? 0;\n  }\n\n  byId(id: number): Notebook | null {\n    return this.list.find((n) => n.id === id) ?? null;\n  }\n\n  async setActive(notebookId: number) {\n    if (this.activeId === notebookId) return;\n    this.activeId = notebookId;\n    try {\n      await notesNotebooksActiveSet(notebookId);\n    } catch (e) {\n      console.warn(\"setActive failed\", e);\n    }\n  }\n\n  async create(args: {\n    name: string;\n    color?: string | null;\n    iconLucide?: string | null;\n  }): Promise<number | null> {\n    try {\n      const r = await notesNotebooksCreate(args);\n      await this.refresh();\n      return r.notebook_id;\n    } catch (e) {\n      console.warn(\"create notebook failed\", e);\n      return null;\n    }\n  }\n","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src/lib/study-notes/notebooks-store.svelte.ts#L78-L114","documentation":"notebooksStore.setActive() optimistically sets this.activeId, then persists the choice with notesNotebooksActiveSet (Tauri command 'study:notes:notebooks:active_set'). If that IPC call rejects, the catch logs 'setActive failed' and the optimistic in-memory activeId is left diverged from the persisted server-side active notebook.","triggerScenarios":"notesNotebooksActiveSet(notebookId) rejects: the command errors on the backend (e.g. target notebook missing/closed), plugin not registered, capability not granted, or IPC failure. Called by close, delete, and switchToIndex.","commonSituations":"Setting active to a notebook that was concurrently closed/deleted on the backend; missing capability entry for the active_set command; backend DB write failure; version skew where the bridge expects a command the installed backend does not expose.","solutions":["Read the logged rejection from notesNotebooksActiveSet for the backend message.","Verify the target notebookId still exists and is open before calling setActive (guard in close/delete paths).","Confirm the 'study:notes:notebooks:active_set' command and its capability permission.","On failure, roll back this.activeId to the previous value so UI state matches the backend.","Add a refresh()/re-read of the active notebook after a failure to resync."],"exampleFix":"// before\nthis.activeId = notebookId;\ntry {\n  await notesNotebooksActiveSet(notebookId);\n} catch (e) {\n  console.warn(\"setActive failed\", e);\n}\n// after\nconst prev = this.activeId;\nthis.activeId = notebookId;\ntry {\n  await notesNotebooksActiveSet(notebookId);\n} catch (e) {\n  console.warn(\"setActive failed\", e);\n  this.activeId = prev; // roll back optimistic update\n}","handlingStrategy":"try-catch","validationCode":"// before switching active\nconst target = notebooksStore.list.find((n) => n.id === notebookId);\nif (!target) { console.warn('setActive: notebook not in list', notebookId); return; }","typeGuard":"function notebookExists(store: NotebooksStore, id: number): boolean {\n  return store.list.some((n) => n.id === id);\n}","tryCatchPattern":"const prev = notebooksStore.activeId;\nawait notebooksStore.setActive(id);\nif (notebooksStore.activeId !== id) {\n  // backend rejected; resync from source of truth\n  await notebooksStore.refresh();\n}","preventionTips":["Roll back optimistic activeId on failure","Never hardcode fallback ids like 1 — pick from the loaded list","Verify the notebook exists before making it active","Keep persisted and in-memory active ids reconciled after errors","Check capabilities cover notes:notebooks:active_set"],"tags":["svelte","tauri","ipc","optimistic-update","state-sync"],"backgroundTag":"api-request-failed","analyzedSha":"8600b91f4246848bac346874daa9e61c1fc5677a","analyzedAt":"2026-09-12T14:29:19.317Z","contentChangedAt":"2026-09-12T14:29:19.317Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}