From cbf646a507afbf7fe5252c19aac99f3b458cda9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20=C3=81ngel?= Date: Wed, 15 Jul 2026 15:53:27 +0000 Subject: [PATCH] fix(render): ignore favicon probe noise --- .../render/stages/probeFailures.test.ts | 22 +++++++++++++++++++ .../services/render/stages/probeFailures.ts | 6 +++++ .../src/services/render/stages/probeStage.ts | 5 ++--- 3 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 packages/producer/src/services/render/stages/probeFailures.test.ts create mode 100644 packages/producer/src/services/render/stages/probeFailures.ts diff --git a/packages/producer/src/services/render/stages/probeFailures.test.ts b/packages/producer/src/services/render/stages/probeFailures.test.ts new file mode 100644 index 0000000000..f26c3418d8 --- /dev/null +++ b/packages/producer/src/services/render/stages/probeFailures.test.ts @@ -0,0 +1,22 @@ +import { describe, expect, it } from "bun:test"; +import { isActionableProbeFailure } from "./probeFailures.js"; + +describe("isActionableProbeFailure", () => { + it("ignores favicon 404 noise without hiding real asset failures", () => { + expect( + isActionableProbeFailure( + "[Browser:HTTP404] GET http://127.0.0.1:4173/favicon.ico resource=image", + ), + ).toBe(false); + expect( + isActionableProbeFailure( + "[Browser:HTTP404] GET http://127.0.0.1:4173/assets/missing.png resource=image", + ), + ).toBe(true); + expect( + isActionableProbeFailure( + "[Browser:REQUESTFAILED] GET http://127.0.0.1:4173/assets/app.js resource=script error=net::ERR_FAILED", + ), + ).toBe(true); + }); +}); diff --git a/packages/producer/src/services/render/stages/probeFailures.ts b/packages/producer/src/services/render/stages/probeFailures.ts new file mode 100644 index 0000000000..4c0ee80d41 --- /dev/null +++ b/packages/producer/src/services/render/stages/probeFailures.ts @@ -0,0 +1,6 @@ +const NETWORK_FAILURE_PATTERN = /404|ERR_NAME_NOT_RESOLVED|ERR_CONNECTION_REFUSED|net::ERR_/i; +const FAVICON_PATTERN = /(?:^|[/?])favicon(?:\.[a-z0-9]+)?(?:[?#\s]|$)/i; + +export function isActionableProbeFailure(line: string): boolean { + return NETWORK_FAILURE_PATTERN.test(line) && !FAVICON_PATTERN.test(line); +} diff --git a/packages/producer/src/services/render/stages/probeStage.ts b/packages/producer/src/services/render/stages/probeStage.ts index 2313a6a916..0c7510f3fd 100644 --- a/packages/producer/src/services/render/stages/probeStage.ts +++ b/packages/producer/src/services/render/stages/probeStage.ts @@ -59,6 +59,7 @@ import { type CompositionMetadata, } from "../shared.js"; import type { RenderJob } from "../../renderOrchestrator.js"; +import { isActionableProbeFailure } from "./probeFailures.js"; export interface ProbeStageInput { projectDir: string; @@ -643,9 +644,7 @@ export async function runProbeStage(input: ProbeStageInput): Promise - /404|ERR_NAME_NOT_RESOLVED|ERR_CONNECTION_REFUSED|net::ERR_/i.test(line), - ); + const failedRequests = probeSession.browserConsoleBuffer.filter(isActionableProbeFailure); if (failedRequests.length > 0) { log.warn("Browser encountered network failures during page load:", { failures: failedRequests.slice(0, 10),