Skip to content

Commit a89e0ba

Browse files
authored
Merge pull request #425 from handsontable/fix/tier1-mount-transport-failure
fix(runner): stop filing the mount's transport failure as a Tier-1 compile error (DEV-3370)
2 parents 1f59579 + ba1b44c commit a89e0ba

3 files changed

Lines changed: 47 additions & 1 deletion

File tree

‎runner/apps/authoring/src/App.tsx‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,7 @@ function reportRuntimeError(e: unknown, engine: string, framework: string): void
313313
causeMessage: e instanceof Error && e.cause instanceof Error ? e.cause.message : null,
314314
replay: e instanceof Error && (e as { replay?: boolean }).replay === true,
315315
online: navigator.onLine,
316+
opaqueNetworkFailure: isOpaqueNetworkFailure(e),
316317
// Widened to the local leg (`dev:full`); the Sentry gate below stays keyed on `monitorDemos`.
317318
monitorDemos: previewMonitoring,
318319
});

‎runner/apps/authoring/src/tier1Report.ts‎

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ export interface Tier1ErrorFacts {
4040
/** `navigator.onLine`. `false` is proof the visitor's network is down, so the failure is
4141
* not ours; `true` proves nothing, so it is not treated as evidence either way. */
4242
online?: boolean;
43+
/** `isOpaqueNetworkFailure(e)`: the browser's own transport failure, e.g. the mount's
44+
* `TypeError: Failed to fetch` when the bundler cannot be reached. */
45+
opaqueNetworkFailure?: boolean;
4346
/** The DEV-2527 demo-monitoring flag. Deliberately an input, so the gate ORDER is tested. */
4447
monitorDemos: boolean;
4548
}
@@ -66,7 +69,7 @@ const COMPILE_TITLE = "Tier-1 compile failed";
6669
/**
6770
* Decide how a Tier-1 error is reported, or that it is not.
6871
*
69-
* Order is load-bearing twice.
72+
* Order is load-bearing three times.
7073
*
7174
* The compiler-asset branch comes **first, ahead of the `monitorDemos` gate**. That flag is
7275
* DEV-2527's temporary demo instrumentation and has a documented teardown
@@ -79,6 +82,10 @@ const COMPILE_TITLE = "Tier-1 compile failed";
7982
* The evaluated-throw stand-down (DEV-2552) comes next: a throw from a module that already
8083
* started evaluating belongs to the in-preview reporter, which files it with the preview's
8184
* own stack, tier, framework and demo id. Reporting it here as well filed one fault twice.
85+
*
86+
* The opaque transport failure (the mount's `TypeError: Failed to fetch`) stands down third,
87+
* after both of those and before the `monitorDemos` gate: it is not a diagnostic about the
88+
* visitor's code, and `sandpack.bundler_unreachable` already counts it.
8289
*/
8390
export function tier1Report(facts: Tier1ErrorFacts): Tier1Report | null {
8491
if (facts.compilerUnavailable) {
@@ -109,6 +116,9 @@ export function tier1Report(facts: Tier1ErrorFacts): Tier1Report | null {
109116
};
110117
}
111118
if (facts.name === "SandpackEvaluationError") return null;
119+
// The bundler never loaded on the visitor's network: nothing about their source, and
120+
// `sandpack.bundler_unreachable` already counts it.
121+
if (facts.opaqueNetworkFailure) return null;
112122
if (!facts.monitorDemos) return null;
113123
return {
114124
tags: { surface: "demo-runtime", kind: "sandpack-compile", tier: "1" },

‎runner/pipeline/tier1-report.test.mjs‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import test from "node:test";
22
import assert from "node:assert/strict";
33
import { tier1Report } from "../apps/authoring/src/tier1Report.ts";
4+
import { isOpaqueNetworkFailure } from "../apps/authoring/src/fetchFailure.ts";
45

56
// DEV-2569 / Sentry DEMOS-15. One issue held two populations — our own compiler chunk
67
// failing to load, and bundler diagnostics over the visitor's half-typed source — and the
@@ -118,6 +119,40 @@ test("a compiler failure whose cause named no URL still reports", () => {
118119
assert.deepEqual(r.fingerprint, ["tier1-compiler-asset"]);
119120
});
120121

122+
// A transport failure is not a diagnostic about the visitor's code, and `sandpack.bundler_unreachable` already counts it.
123+
test("the mount's opaque transport failure is not a compile error report", () => {
124+
assert.equal(
125+
tier1Report(compile({ name: "TypeError", message: "Failed to fetch", opaqueNetworkFailure: true })),
126+
null,
127+
);
128+
});
129+
130+
// Mirrors the App.tsx call site: `opaqueNetworkFailure: isOpaqueNetworkFailure(e)`.
131+
const factsFor = (e) => compile({
132+
name: e.name,
133+
message: e.message,
134+
opaqueNetworkFailure: isOpaqueNetworkFailure(e),
135+
});
136+
137+
test("a real `TypeError: Failed to fetch` runs through the classifier and is not reported", () => {
138+
assert.equal(tier1Report(factsFor(new TypeError("Failed to fetch"))), null);
139+
});
140+
141+
test("a real compile error runs through the classifier and is still reported", () => {
142+
const err = new Error(CODE_FRAME);
143+
err.name = "SandpackCompileError";
144+
assert.ok(tier1Report(factsFor(err)));
145+
});
146+
147+
test("a visitor compile error is still reported when the transport flag is false or absent", () => {
148+
assert.ok(tier1Report(compile({ opaqueNetworkFailure: false })));
149+
assert.ok(tier1Report(compile()));
150+
});
151+
152+
test("the transport stand-down does not cover the compiler-asset branch", () => {
153+
assert.ok(tier1Report(compilerAsset({ opaqueNetworkFailure: true })));
154+
});
155+
121156
test("every tag value is a non-empty string", () => {
122157
for (const facts of [compile(), compilerAsset()]) {
123158
const r = tier1Report(facts);

0 commit comments

Comments
 (0)