block/buzz · info · DOMException
Media fetch cancelled
Error message
Media fetch cancelled
What it means
fetchMediaBytes downloads media bytes via the Tauri command `fetch_media_bytes` and accepts an optional AbortSignal for cancellation. If the signal is already aborted at entry, it throws a DOMException AbortError named 'Media fetch cancelled' instead of making the IPC call. This is intentional fast-fail semantics so callers can treat it uniformly with mid-flight cancellations.
Source
Thrown at desktop/src/shared/api/tauriMedia.ts:90
*/
export async function pickAndUploadImage(): Promise<BlobDescriptor | null> {
return invokeTauri<BlobDescriptor | null>("pick_and_upload_image", {});
}
/**
* Fetch relay media bytes over IPC (Rust reqwest, VPN-tunneled).
*
* Used by the composer image editor: wrapping the bytes in a same-origin
* `blob:` URL gives the canvas pixel access without CORS, so the media
* proxy needs no special headers. The Rust side enforces the same URL
* validation and size cap as the download commands.
*/
export async function fetchMediaBytes(
url: string,
signal?: AbortSignal,
): Promise<Uint8Array<ArrayBuffer>> {
if (signal?.aborted) {
throw new DOMException("Media fetch cancelled", "AbortError");
}
const requestId = signal ? crypto.randomUUID() : undefined;
// The Rust command replies with `tauri::ipc::Response`, so the bytes
// arrive as a raw ArrayBuffer rather than a JSON number array.
const request = invokeTauri<ArrayBuffer>("fetch_media_bytes", {
requestId,
url,
});
if (!signal || !requestId) return new Uint8Array(await request);
let rejectCancellation: ((reason?: unknown) => void) | undefined;
const cancellation = new Promise<never>((_resolve, reject) => {
rejectCancellation = reject;
});
const onAbort = () => {
void invokeTauri("cancel_media_fetch", { requestId })
.catch(() => undefined)View on GitHub (pinned to dad5a33865)
Solutions
- Check signal.aborted before calling fetchMediaBytes and skip the call if already aborted
- Create a fresh AbortController per fetch instead of reusing a shared one that may already be aborted
- Catch AbortError (e.name === 'AbortError') and treat it as a benign no-op rather than logging it as a failure
Example fix
// before
const bytes = await fetchMediaBytes(url, controller.signal);
// after
if (controller.signal.aborted) return;
try {
const bytes = await fetchMediaBytes(url, controller.signal);
} catch (e) {
if ((e as DOMException).name === 'AbortError') return; // benign cancellation
throw e;
} Defensive patterns
Strategy: try-catch
Validate before calling
if (signal?.aborted) return; // skip the fetch entirely
Type guard
function isAbortError(e: unknown): e is DOMException {
return e instanceof DOMException && e.name === 'AbortError';
} Try / catch
try {
const bytes = await fetchMediaBytes(url, signal);
} catch (e) {
if (isAbortError(e)) return null; // benign cancellation
throw e;
} Prevention
- Create one AbortController per fetch lifecycle, not shared across loads
- Check signal.aborted before initiating any async work
- Never log AbortError as an error — filter it in catch blocks
When it happens
Trigger: Calling fetchMediaBytes (directly or via load/bytes helpers) with an AbortSignal that has already been aborted — e.g. a component unmounted before the download started, or a race where abort() fires between scheduling the call and entering the function.
Common situations: React effect cleanup aborts a controller before the async media fetch begins; a user closes an attachment viewer while its media is queued; parallel loads share one controller and one completes first.
Related errors
- Audio decode cancelled
- {error} (and the local stores could not be restored: {restor
- invalid media config: {e}
- failed to initialize media storage: {e}
- upload cancelled
AI-assisted analysis of block/buzz@dad5a33865 (2026-09-05).
Data as JSON: /api/errors/c487b9a390c6f9f8.
Report an issue: GitHub.