actualbudget/actual · error
Cannot delete the last dashboard page
Error message
Cannot delete the last dashboard page
What it means
deleteDashboardPage refuses to delete a dashboard page when fewer than 2 non-tombstoned pages exist. Actual requires at least one dashboard page to remain, so deleting the last one is blocked with this plain Error.
Source
Thrown at packages/loot-core/src/server/dashboard/app.ts:122
}
});
},
};
async function createDashboardPage({ name }: { name: string }) {
const id = uuidv4();
await db.insertWithSchema('dashboard_pages', { id, name });
return id;
}
async function deleteDashboardPage(id: string) {
const res = await db.first<{ c: number }>(
'SELECT count(*) as c FROM dashboard_pages WHERE tombstone = 0',
);
if ((res?.c ?? 0) <= 1) {
throw new Error('Cannot delete the last dashboard page');
}
const deleting_widgets = await db.all<Pick<db.DbDashboard, 'id'>>(
'SELECT id FROM dashboard WHERE dashboard_page_id = ? AND tombstone = 0',
[id],
);
await batchMessages(async () => {
await db.delete_('dashboard_pages', id);
// Tombstone all widgets for this dashboard
await Promise.all(
deleting_widgets.map(({ id }) => db.delete_('dashboard', id)),
);
});
}
async function renameDashboardPage({ id, name }: { id: string; name: string }) {
await db.updateWithSchema('dashboard_pages', { id, name });View on GitHub (pinned to d4334cb6e6)
Solutions
- Create another dashboard page first (dashboard-page-create), then delete the unwanted page.
- Keep the last page and clear its widgets instead of deleting the page itself.
- Catch the error in UI/script code and treat 'last page' as a no-op.
Example fix
// before
await runMutator(() => deleteDashboardPage(pageId));
// after
const pages = await getDashboardPages();
if (pages.length > 1) {
await runMutator(() => deleteDashboardPage(pageId));
} Defensive patterns
Strategy: try-catch
Validate before calling
const pages = await send('dashboard-get-pages');
if (pages.length <= 1) {
throw new Error('Refusing to delete the last dashboard page');
} Try / catch
try {
await send('dashboard-delete-page', { id });
} catch (e) {
if (e.message === 'Cannot delete the last dashboard page') {
console.warn('Keep at least one dashboard page; create a new page first.');
}
} Prevention
- Check the page count before batch-deleting pages and stop at one.
- Disable the delete action in UI/scripts when only one page exists.
- Delete widgets rather than the final page when clearing a dashboard.
When it happens
Trigger: Calling the deleteDashboardPage handler (e.g. via 'dashboard-page-delete' from the UI or API) when the dashboard_pages table has exactly one row with tombstone = 0.
Common situations: Users or scripts cleaning up dashboard pages who don't realize the final default page cannot be removed; automated cleanup that deletes pages one by one until only one remains and then tries to delete it.
Related errors
- Unsupported widget type: ${widget.type}
- Invalid dashboard.widgets data type: it must be an array of
- Invalid widget.${idx}.x data-type for value ${widget.x}.
- Invalid widget.${idx}.y data-type for value ${widget.y}.
- Invalid widget.${idx}.width data-type for value ${widget.wid
AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29).
Data as JSON: /api/errors/e1c4cb8bcc050a60.
Report an issue: GitHub.