schollz/croc · info · DOMException
AbortError
AbortError
Error message
Destination selection cancelled
What it means
Thrown as a DOMException with name AbortError by chooseReceiveDestination after the user was shown a window.confirm overwrite dialog for existing files in the picked directory and declined to replace them. It signals deliberate user cancellation of destination selection, not a system failure. Existing-file detection is done per offer file via fileExists() against the picked directory handle.
Source
Thrown at web/src/protocol/storage.ts:362
window.location.hostname === "localhost" ||
window.location.hostname === "127.0.0.1")
);
}
export async function chooseReceiveDestination(offer: TransferOffer) {
if (!window.showDirectoryPicker) return new DownloadDestination();
const directory = await window.showDirectoryPicker({ mode: "readwrite" });
const collisions: string[] = [];
for (const file of offer.files) {
if (await fileExists(directory, file)) collisions.push(file.path);
}
if (
collisions.length > 0 &&
!window.confirm(
`${collisions.length} file${collisions.length === 1 ? "" : "s"} already exist in that folder. Replace them?`,
)
) {
throw new DOMException("Destination selection cancelled", "AbortError");
}
return new DirectoryDestination(directory);
}
export async function chooseStoredReceiveDestination(offer: TransferOffer) {
if (window.showDirectoryPicker) {
return chooseReceiveDestination(offer);
}
if (supportsStreamingDownloadDestination()) {
return new StreamingDownloadDestination();
}
const largest = offer.files.reduce(
(maximum, file) => Math.max(maximum, file.size),
0,
);
if (largest > 256 * 1024 * 1024) {
throw new Error(
"This browser cannot stream a file this large. Receive it with the croc CLI instead.",View on GitHub (pinned to e25f1bdc04)
Solutions
- Catch DOMException with name === "AbortError" around chooseReceiveDestination/chooseStoredReceiveDestination and treat it as a benign user cancel (stop quietly or re-prompt)
- If the user should proceed, instruct them to confirm the replace dialog or pick a different/empty folder
- Pre-clean or rename colliding files in the target folder before re-running the receive
Example fix
// before
const destination = await chooseReceiveDestination(offer);
// after
try {
const destination = await chooseReceiveDestination(offer);
} catch (error) {
if (error instanceof DOMException && error.name === "AbortError") return; // user cancelled
throw error;
} Defensive patterns
Strategy: try-catch
Type guard
const isUserCancel = (e: unknown): boolean => e instanceof DOMException && e.name === "AbortError";
Try / catch
try { destination = await chooseStoredReceiveDestination(offer); } catch (e) { if (e instanceof DOMException && e.name === "AbortError") { showCancelledState(); return; } throw e; } Prevention
- Treat AbortError from destination selection as a first-class UI state (cancelled), not an error toast
- Remember it can come from either the directory picker itself or the overwrite confirm — handle both the same way
When it happens
Trigger: window.showDirectoryPicker({mode:"readwrite"}) succeeds, one or more offered file paths already exist in the chosen folder, and the user clicks Cancel on the "N file(s) already exist in that folder. Replace them?" confirm dialog.
Common situations: Re-running a receive into the same folder after a partial earlier transfer; receivers who deliberately do not want to clobber existing data. Note the directory picker's own Cancel produces a different AbortError from showDirectoryPicker itself, so catch code must handle both origins gracefully.
Related errors
AI-assisted analysis of schollz/croc@e25f1bdc04 (2026-08-15).
Data as JSON: /api/errors/e1a2f93af30c4093.
Report an issue: GitHub.