tonhowtf/omniget · warning
close failed
Error message
close failed
What it means
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.
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.
Example fix
// before
if (this.activeId === notebookId) {
await this.setActive(1);
}
// after
if (this.activeId === notebookId) {
const fallback = this.list.find((n) => n.id !== notebookId && !n.closed) ?? this.list.find((n) => n.id !== notebookId);
if (fallback) await this.setActive(fallback.id);
} Defensive patterns
Strategy: try-catch
Validate before calling
const nb = notebooksStore.list.find((n) => n.id === notebookId);
if (!nb) return; // nothing to close
if (nb.closed) { await notebooksStore.refresh(); return; } // already closed Type guard
function isClosable(nb: Notebook | undefined): nb is Notebook {
return !!nb && !nb.closed;
} Try / catch
try {
await notebooksStore.close(notebookId);
} catch (e) {
console.warn('close rejected:', e);
showToast('Could not close notebook');
await notebooksStore.refresh(); // resync open/closed state
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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).
Understand the failure class
Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.
Related errors
- notebooksStore.hydrate failed
- notebooksStore.refresh failed
- setActive failed
- create notebook failed
- rename failed
AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12).
Data as JSON: /api/errors/566282c2b8f65e3c.
Report an issue: GitHub.
Appendix: source
Thrown at src/lib/study-notes/notebooks-store.svelte.ts:132
async rename(notebookId: number, newName: string) {
try {
await notesNotebooksRename({ notebookId, newName });
await this.refresh();
} catch (e) {
console.warn("rename failed", e);
}
}
async close(notebookId: number) {
try {
await notesNotebooksClose(notebookId);
if (this.activeId === notebookId) {
await this.setActive(1);
}
await this.refresh();
} catch (e) {
console.warn("close failed", e);
}
}
async reopen(notebookId: number) {
try {
await notesNotebooksReopen(notebookId);
await this.refresh();
} catch (e) {
console.warn("reopen failed", e);
}
}
async delete(notebookId: number, force = false): Promise<NotebookDeleteReport> {
try {
const r = await notesNotebooksDelete({ notebookId, force });
if (r.deleted && this.activeId === notebookId) {
await this.setActive(1);
}View on GitHub (pinned to 8600b91f42)