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

  1. Read the logged rejection to see whether close, setActive(1), or refresh failed.
  2. If the backend says the notebook is already closed, treat it as success and just refresh().
  3. Check that the hardcoded fallback target setActive(1) is valid — prefer falling back to the first existing notebook.
  4. Verify the 'study:notes:notebooks:close' command and capability registration.
  5. 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

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


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)