Client: _fetch had no timeout — a hung request (server accepted the connection but never responds) spun the UI forever with no error. Now wrapped in AbortSignal.timeout(120s, generous enough for the slowest legit import/sync/backup on a LAN) and both timeout and network failure map to a clean ApiError (REQUEST_TIMEOUT / NETWORK_ERROR) so they surface as a normal error toast instead of a freeze or raw 'Failed to fetch'. Server: the global error handler now returns next(err) when res.headersSent, so an error after a partial response can't throw 'cannot set headers'. (The async-handler-hang gap is folded into the Express 5 upgrade in Phase 2.2, which forwards async rejections natively — no throwaway wrapper.) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| components | ||
| contexts | ||
| hooks | ||
| lib | ||
| pages | ||
| public/img | ||
| App.tsx | ||
| api.ts | ||
| index.css | ||
| main.tsx | ||
| types.ts | ||