{"record":{"id":"566282c2b8f65e3c","repo":"tonhowtf/omniget","slug":"close-failed","errorCode":null,"errorMessage":"close failed","messagePattern":"close failed","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/lib/study-notes/notebooks-store.svelte.ts","lineNumber":132,"sourceCode":"\n  async rename(notebookId: number, newName: string) {\n    try {\n      await notesNotebooksRename({ notebookId, newName });\n      await this.refresh();\n    } catch (e) {\n      console.warn(\"rename failed\", e);\n    }\n  }\n\n  async close(notebookId: number) {\n    try {\n      await notesNotebooksClose(notebookId);\n      if (this.activeId === notebookId) {\n        await this.setActive(1);\n      }\n      await this.refresh();\n    } catch (e) {\n      console.warn(\"close failed\", e);\n    }\n  }\n\n  async reopen(notebookId: number) {\n    try {\n      await notesNotebooksReopen(notebookId);\n      await this.refresh();\n    } catch (e) {\n      console.warn(\"reopen failed\", e);\n    }\n  }\n\n  async delete(notebookId: number, force = false): Promise<NotebookDeleteReport> {\n    try {\n      const r = await notesNotebooksDelete({ notebookId, force });\n      if (r.deleted && this.activeId === notebookId) {\n        await this.setActive(1);\n      }","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src/lib/study-notes/notebooks-store.svelte.ts#L114-L150","documentation":"notebooksStore.close() closes a notebook via notesNotebooksClose (Tauri command 'study:notes:notebooks:close'), re-points the active notebook to id 1 if the closed one was active (via setActive), then refresh(). If any of these steps rejects, the catch logs 'close failed' and the notebook may remain open or the active pointer may be stale.","triggerScenarios":"notesNotebooksClose(notebookId) rejects (notebook already closed/missing, backend error, IPC failure), or the follow-up this.setActive(1) / this.refresh() throws — setActive and refresh have their own try/catch, so a failure here most often originates in notesNotebooksClose itself.","commonSituations":"Closing a notebook already closed in another session; notebook deleted concurrently so close() hits a missing entity; DB write failure; missing capability for the close command; the fallback setActive(1) failing because notebook id 1 no longer exists (hardcoded default).","solutions":["Read the logged rejection to see whether close, setActive(1), or refresh failed.","If the backend says the notebook is already closed, treat it as success and just refresh().","Check that the hardcoded fallback target setActive(1) is valid — prefer falling back to the first existing notebook.","Verify the 'study:notes:notebooks:close' command and capability registration.","Resolve DB lock/write errors reported by the backend before retrying."],"exampleFix":"// before\nif (this.activeId === notebookId) {\n  await this.setActive(1);\n}\n// after\nif (this.activeId === notebookId) {\n  const fallback = this.list.find((n) => n.id !== notebookId && !n.closed) ?? this.list.find((n) => n.id !== notebookId);\n  if (fallback) await this.setActive(fallback.id);\n}","handlingStrategy":"try-catch","validationCode":"const nb = notebooksStore.list.find((n) => n.id === notebookId);\nif (!nb) return; // nothing to close\nif (nb.closed) { await notebooksStore.refresh(); return; } // already closed","typeGuard":"function isClosable(nb: Notebook | undefined): nb is Notebook {\n  return !!nb && !nb.closed;\n}","tryCatchPattern":"try {\n  await notebooksStore.close(notebookId);\n} catch (e) {\n  console.warn('close rejected:', e);\n  showToast('Could not close notebook');\n  await notebooksStore.refresh(); // resync open/closed state\n}","preventionTips":["Skip close if the notebook is already closed","Choose the post-close active fallback from the list instead of hardcoding id 1","Refresh after any close failure to restore accurate state","Confirm capabilities include notes:notebooks:close","Watch console warnings after multi-window usage where state may diverge"],"tags":["svelte","tauri","ipc","state-sync","error-handling"],"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"}