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
- 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.
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
- 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
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
- close failed
- notebooksStore.hydrate failed
- notebooksStore.refresh failed
- create notebook failed
- rename failed
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)