actualbudget/actual · info · PostError
aborted
aborted
Error message
aborted
What it means
PostError with sentinel message 'aborted' thrown by post when the caller-supplied AbortSignal fired and fetch rejected with an AbortError — i.e. the request was cancelled by the caller, not a timeout or network fault.
Source
Thrown at packages/loot-core/src/server/post.ts:86
try {
const signal = timeout != null || externalSignal ? controller.signal : null;
res = await fetch(url, {
method: 'POST',
body: JSON.stringify(data),
signal,
headers: {
...headers,
'Content-Type': 'application/json',
},
});
text = await res.text();
} catch (err) {
if (
err instanceof Error &&
err.name === 'AbortError' &&
externalSignal?.aborted
) {
throw new PostError('aborted');
}
throw new PostError('network-failure', undefined, { cause: err });
} finally {
if (timeoutId != null) clearTimeout(timeoutId);
externalSignal?.removeEventListener('abort', onExternalAbort);
}
throwIfNot200(res, text);
let responseData;
try {
responseData = JSON.parse(text);
} catch {
// Something seriously went wrong. TODO handle errors
throw new PostError('parse-json', { meta: text });
}
View on GitHub (pinned to d4334cb6e6)
Solutions
- Catch PostError 'aborted' and treat it as an expected cancellation, not a failure
- Only abort the signal when cancellation is truly intended
- If aborts are accidental, stop aborting controllers on unmount/hide
- Re-issue the request if the operation must complete
Example fix
// before
try { await post(url, data, { signal: controller.signal }); } catch (e) { throw e; }
// after
try { await post(url, data, { signal: controller.signal }); }
catch (e) {
if (e instanceof PostError && e.message === 'aborted') return; // cancelled by us
throw e;
} Defensive patterns
Strategy: try-catch
Validate before calling
// only wire an AbortController if cancellation is genuinely needed const controller = shouldAllowCancel ? new AbortController() : null;
Type guard
function isAbortError(e: unknown): e is PostError {
return e instanceof PostError && e.message === 'aborted';
} Try / catch
try {
await post(url, data, { signal: controller?.signal });
} catch (e) {
if (isAbortError(e)) return; // expected cancellation — ignore
throw e;
} Prevention
- Treat 'aborted' as success-path cancellation, never surface it as a user-facing error
- Only abort requests that are safe to abandon
- Track controller lifetime with the UI element that owns the request
- Don't reuse an already-aborted AbortController for new requests
When it happens
Trigger: Passing an externalSignal to post() and aborting it (via AbortController.abort()) while the request is in flight; component unmount cancelling a sync request.
Common situations: UI cancelling a slow sync when navigating away, user pressing a cancel button, React effects aborting fetches on cleanup, duplicate-request suppression aborting the older call.
Related errors
- Could not resolve on-disk budget id for syncId ${syncId} aft
- results.reason || results.error_code
- results.reason || results.error
- Failed to fetch catalog: ${response.statusText}
- Failed to fetch CSS from ${url}: ${response.status} ${respon
AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29).
Data as JSON: /api/errors/7530704ecec5fec8.
Report an issue: GitHub.