Skip to content

Commit ce577b0

Browse files
committed
Simplify error propagation and alerts
1 parent 575c13f commit ce577b0

5 files changed

Lines changed: 28 additions & 12 deletions

File tree

web/src/lib/components/files/MultimodalFileInput.svelte

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
fileTypeOverride: box.with(() => fileTypeOverride),
1515
defaultMode: box.with(() => defaultMode),
1616
});
17+
18+
// eslint-disable-next-line no-useless-assignment -- false positive for Svelte $bindable initialization
1719
state = instance;
1820
1921
function handleDragOver(event: DragEvent) {

web/src/lib/components/files/index.svelte.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,9 @@ export class MultimodalFileInputState {
236236
if (threw) {
237237
throw e;
238238
}
239-
throw new Error(`Failed to fetch from URL: ${url}\nSome errors, such as those caused by CORS, will only print in the console.\nCause: ${e}`);
239+
throw new Error(`Failed to fetch from URL: ${url}\nSome errors, such as those caused by CORS, will only print in the console.`, {
240+
cause: e,
241+
});
240242
}
241243
});
242244
});

web/src/lib/diff-viewer.svelte.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import {
1919
parseLineRef,
2020
type UnresolvedLineSelection,
2121
} from "$lib/components/diff/concise-diff-view.svelte";
22-
import { countOccurrences, type LazyPromise, lazyPromise, animationFramePromise, yieldToBrowser } from "$lib/util";
22+
import { countOccurrences, type LazyPromise, lazyPromise, animationFramePromise, formatErrorWithCauses, yieldToBrowser } from "$lib/util";
2323
import { onDestroy, onMount, tick } from "svelte";
2424
import { VList } from "virtua/svelte";
2525
import { Context, Debounced, watch } from "runed";
@@ -740,7 +740,7 @@ export class MultiFileDiffViewerState {
740740
} catch (e) {
741741
this.clear(); // Clear any partially loaded state
742742
console.error("Failed to load patches:", e);
743-
alert("Failed to load patches: " + e);
743+
alert(formatErrorWithCauses(e));
744744
return false;
745745
} finally {
746746
// Let the last progress update render before closing the loading state

web/src/lib/open-diff-dialog.svelte.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { DirectoryEntry, FileEntry, MultimodalFileInputState, type MultimodalFil
33
import { SvelteSet } from "svelte/reactivity";
44
import { type FileStatus } from "$lib/github.svelte";
55
import { makeImageDetails, makeTextDetails, MultiFileDiffViewerState, type LoadPatchesOptions } from "$lib/diff-viewer.svelte";
6-
import { binaryFileDummyDetails, bytesEqual, isBinaryFile, isImageFile, parseMultiFilePatch, tryCompileRegex } from "$lib/util";
6+
import { binaryFileDummyDetails, bytesEqual, formatErrorWithCauses, isBinaryFile, isImageFile, parseMultiFilePatch, tryCompileRegex } from "$lib/util";
77
import { createTwoFilesPatch } from "diff";
88

99
export interface OpenDiffDialogProps {
@@ -77,13 +77,7 @@ export class OpenDiffDialogState {
7777
},
7878
async () => {
7979
const isImageDiff = isImageFile(fileAMeta.name) && isImageFile(fileBMeta.name);
80-
let blobA: Blob, blobB: Blob;
81-
try {
82-
[blobA, blobB] = await Promise.all([fileA.resolve(), fileB.resolve()]);
83-
} catch (e) {
84-
console.log("Failed to resolve files:", e);
85-
throw new Error("Failed to resolve files", { cause: e });
86-
}
80+
const [blobA, blobB] = await Promise.all([fileA.resolve(), fileB.resolve()]);
8781
const [aBinary, bBinary] = await Promise.all([isBinaryFile(blobA), isBinaryFile(blobB)]);
8882
if (aBinary || bBinary) {
8983
if (!isImageDiff) {
@@ -262,7 +256,7 @@ export class OpenDiffDialogState {
262256
text = await blob.text();
263257
} catch (e) {
264258
console.error("Failed to resolve patch file:", e);
265-
alert("Failed to resolve patch file: " + e);
259+
alert(formatErrorWithCauses(e));
266260
return;
267261
}
268262
this.props.open.current = false;

web/src/lib/util.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,24 @@ export function capitalizeFirstLetter(val: string): string {
374374
return val.charAt(0).toUpperCase() + val.slice(1);
375375
}
376376

377+
export function formatErrorWithCauses(error: unknown): string {
378+
const parts: string[] = [];
379+
const seen = new Set<unknown>();
380+
let current: unknown = error;
381+
382+
while (current !== undefined && !seen.has(current)) {
383+
seen.add(current);
384+
parts.push(String(current));
385+
386+
if (!(current instanceof Error) || current.cause === undefined) {
387+
break;
388+
}
389+
current = current.cause;
390+
}
391+
392+
return parts.map((part, index) => (index === 0 ? part : `Cause: ${part}`)).join("\n");
393+
}
394+
377395
export function countOccurrences(str: string, substr: string): number {
378396
let count = 0;
379397
let idx = 0;

0 commit comments

Comments
 (0)