What
The dashboard's manual refresh can silently skip every data/quota refresh when local sync fails.
handleManualRefresh places await triggerLocalSync() and await refreshAll(...) inside the same try. In local mode, any sync rejection jumps directly to the catch block, so refreshAll is never called. The refresh button stops loading after logging to the console, but the dashboard remains stale.
This was reproduced during PR #142's Vite smoke because /api/local-auth returned 404 and triggerLocalSync() rejected. It is pre-existing and deliberately excluded from #142, whose scope is scheduled quota-cache behavior.
Evidence
Current control flow in dashboard/src/pages/DashboardPage.jsx, handleManualRefresh:
try {
if (isLocalMode) {
await triggerLocalSync();
}
await refreshAll({ forceUsageLimits: true });
} catch (error) {
console.error("[DashboardPage] Refresh failed:", error);
}
The sync step and refresh step have different failure semantics but share one catch boundary.
Impact
A user explicitly pressing refresh receives no fresh dashboard or quota data if local sync has a transient/API failure. Because the button returns to normal and the error is console-only, this looks like a successful no-op.
Suggested shape
Treat sync and refresh as independent deposits:
- Attempt local sync and preserve/report its failure.
- Still run
refreshAll({ forceUsageLimits: true }) so already-available data and provider quotas refresh.
- Keep loading state correct until both attempted operations finish.
- Avoid converting the failure into silent success; use the existing user-visible error mechanism if one exists, otherwise track the missing UX explicitly.
Definition of done
Scope
Do not change scheduled refresh semantics from PR #142 in this issue.
What
The dashboard's manual refresh can silently skip every data/quota refresh when local sync fails.
handleManualRefreshplacesawait triggerLocalSync()andawait refreshAll(...)inside the sametry. In local mode, any sync rejection jumps directly to the catch block, sorefreshAllis never called. The refresh button stops loading after logging to the console, but the dashboard remains stale.This was reproduced during PR #142's Vite smoke because
/api/local-authreturned 404 andtriggerLocalSync()rejected. It is pre-existing and deliberately excluded from #142, whose scope is scheduled quota-cache behavior.Evidence
Current control flow in
dashboard/src/pages/DashboardPage.jsx,handleManualRefresh:The sync step and refresh step have different failure semantics but share one catch boundary.
Impact
A user explicitly pressing refresh receives no fresh dashboard or quota data if local sync has a transient/API failure. Because the button returns to normal and the error is console-only, this looks like a successful no-op.
Suggested shape
Treat sync and refresh as independent deposits:
refreshAll({ forceUsageLimits: true })so already-available data and provider quotas refresh.Definition of done
triggerLocalSync()does not preventrefreshAll().DashboardPage, rejects the sync mock, and asserts the refresh hooks still run.npm run ci:localpasses.Scope
Do not change scheduled refresh semantics from PR #142 in this issue.