tonhowtf/omniget · warning

setActive failed

Error message

setActive failed

What it means

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.

Solutions

  1. Read the logged rejection from notesNotebooksActiveSet for the backend message.
  2. Verify the target notebookId still exists and is open before calling setActive (guard in close/delete paths).
  3. Confirm the 'study:notes:notebooks:active_set' command and its capability permission.
  4. On failure, roll back this.activeId to the previous value so UI state matches the backend.
  5. Add a refresh()/re-read of the active notebook after a failure to resync.

Example fix

// before
this.activeId = notebookId;
try {
  await notesNotebooksActiveSet(notebookId);
} catch (e) {
  console.warn("setActive failed", e);
}
// after
const prev = this.activeId;
this.activeId = notebookId;
try {
  await notesNotebooksActiveSet(notebookId);
} catch (e) {
  console.warn("setActive failed", e);
  this.activeId = prev; // roll back optimistic update
}
Defensive patterns

Strategy: try-catch

Validate before calling

// before switching active
const target = notebooksStore.list.find((n) => n.id === notebookId);
if (!target) { console.warn('setActive: notebook not in list', notebookId); return; }

Type guard

function notebookExists(store: NotebooksStore, id: number): boolean {
  return store.list.some((n) => n.id === id);
}

Try / catch

const prev = notebooksStore.activeId;
await notebooksStore.setActive(id);
if (notebooksStore.activeId !== id) {
  // backend rejected; resync from source of truth
  await notebooksStore.refresh();
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

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/073d9847b276fe69. Report an issue: GitHub.

Appendix: source

Thrown at src/lib/study-notes/notebooks-store.svelte.ts:96

      console.warn("notebooksStore.refresh failed", e);
    }
  }

  pageCountOf(id: number): number {
    return this.list.find((n) => n.id === id)?.page_count ?? 0;
  }

  byId(id: number): Notebook | null {
    return this.list.find((n) => n.id === id) ?? null;
  }

  async setActive(notebookId: number) {
    if (this.activeId === notebookId) return;
    this.activeId = notebookId;
    try {
      await notesNotebooksActiveSet(notebookId);
    } catch (e) {
      console.warn("setActive failed", e);
    }
  }

  async create(args: {
    name: string;
    color?: string | null;
    iconLucide?: string | null;
  }): Promise<number | null> {
    try {
      const r = await notesNotebooksCreate(args);
      await this.refresh();
      return r.notebook_id;
    } catch (e) {
      console.warn("create notebook failed", e);
      return null;
    }
  }

View on GitHub (pinned to 8600b91f42)