mirror of
https://github.com/morluto/rea.git
synced 2026-10-26 17:35:11 +00:00
fix(browser): report Windows HAR heap exhaustion (#1147)
Recognize exit code 134 without a signal when the HAR decoder reports V8 heap exhaustion. Preserve the observed termination in the memory failure and cover Windows, POSIX, and unrelated decoder failures.
This commit is contained in:
1 parent
441813c070
commit
13935077ba
3 files changed
+85
-3
No files matched your search
@@ -7,6 +7,83 @@ import { historicalCaptureFailure } from "./CaptureFailures.js";
|
||||
import { redactExplicitFailure } from "../../domain/explicitSensitiveFailure.js";
|
||||
import { OwnedCommandFailure } from "../../process/OwnedCommand.js";
|
||||
|
||||
it.each([
|
||||
{ label: "POSIX SIGABRT", exitCode: null, signal: "SIGABRT" },
|
||||
{ label: "Windows exit 134", exitCode: 134, signal: null },
|
||||
] as const)(
|
||||
"reports HAR heap exhaustion for $label",
|
||||
({ exitCode, signal }) => {
|
||||
const input = inspectWebNetworkCaptureInputSchema.parse({
|
||||
capture_path: "/selected/input.har",
|
||||
format: "har",
|
||||
});
|
||||
const stderr =
|
||||
"FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory\r\n";
|
||||
const cause = new OwnedCommandFailure("process", "Decoder failed", {
|
||||
stdout: { text: "", bytes: 0 },
|
||||
stderr: { text: stderr, bytes: Buffer.byteLength(stderr) },
|
||||
exitCode,
|
||||
signal,
|
||||
});
|
||||
const projected = analysisErrorProjectionSchema.parse(
|
||||
projectAnalysisError(historicalCaptureFailure(input, cause, "decoder")),
|
||||
);
|
||||
expect(projected).toMatchObject({
|
||||
code: "resource_constraint",
|
||||
retryable: false,
|
||||
message: expect.stringContaining("fixed V8 heap"),
|
||||
remediation: {
|
||||
action: expect.stringContaining(
|
||||
"smaller capture exported by its producer",
|
||||
),
|
||||
},
|
||||
details: {
|
||||
resource: "memory",
|
||||
reported_limits: {
|
||||
observed_exit_code: exitCode,
|
||||
observed_signal: signal,
|
||||
},
|
||||
captured_output: { stdout: "", stderr },
|
||||
},
|
||||
});
|
||||
expect(JSON.stringify(projected)).not.toContain("rea doctor");
|
||||
},
|
||||
);
|
||||
|
||||
it.each([
|
||||
{ exitCode: 134, signal: null, stderr: "Fatal decoder crash" },
|
||||
{
|
||||
exitCode: 2,
|
||||
signal: null,
|
||||
stderr: "FATAL ERROR: JavaScript heap out of memory",
|
||||
},
|
||||
{
|
||||
exitCode: null,
|
||||
signal: "SIGTERM",
|
||||
stderr: "FATAL ERROR: JavaScript heap out of memory",
|
||||
},
|
||||
] as const)(
|
||||
"preserves unrelated decoder failures %#",
|
||||
({ exitCode, signal, stderr }) => {
|
||||
const input = inspectWebNetworkCaptureInputSchema.parse({
|
||||
capture_path: "/selected/input.har",
|
||||
format: "har",
|
||||
});
|
||||
const cause = new OwnedCommandFailure("process", "Decoder failed", {
|
||||
stdout: { text: "", bytes: 0 },
|
||||
stderr: { text: stderr, bytes: Buffer.byteLength(stderr) },
|
||||
exitCode,
|
||||
signal,
|
||||
});
|
||||
expect(
|
||||
projectAnalysisError(historicalCaptureFailure(input, cause, "decoder")),
|
||||
).toMatchObject({
|
||||
code: "execution_failure",
|
||||
details: { diagnostics: { exit_code: exitCode, signal, stderr } },
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
it.each(["before open", "during read"])(
|
||||
"preserves observed capture changes %s as retryable acquisition integrity failures",
|
||||
(stage) => {
|
||||
|
||||
@@ -61,7 +61,8 @@ export const historicalCaptureFailure = (
|
||||
phase === "decoder" &&
|
||||
input.format === "har" &&
|
||||
cause.reason === "process" &&
|
||||
cause.snapshot?.signal === "SIGABRT" &&
|
||||
(cause.snapshot?.signal === "SIGABRT" ||
|
||||
(cause.snapshot?.signal === null && cause.snapshot.exitCode === 134)) &&
|
||||
/FATAL ERROR:[^\r\n]*heap out of memory/u.test(cause.snapshot.stderr.text)
|
||||
)
|
||||
return captureMemoryFailure(
|
||||
@@ -182,7 +183,10 @@ export const captureMemoryFailure = (
|
||||
}
|
||||
: {}),
|
||||
...(cause instanceof OwnedCommandFailure
|
||||
? { observed_signal: cause.snapshot?.signal ?? null }
|
||||
? {
|
||||
observed_exit_code: cause.snapshot?.exitCode ?? null,
|
||||
observed_signal: cause.snapshot?.signal ?? null,
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
{
|
||||
|
||||
@@ -70,7 +70,8 @@ it("reports real HAR heap exhaustion through CLI and MCP and preserves server us
|
||||
resource: "memory",
|
||||
reported_limits: {
|
||||
old_generation_heap_mib: 192,
|
||||
observed_signal: "SIGABRT",
|
||||
observed_exit_code: process.platform === "win32" ? 134 : null,
|
||||
observed_signal: process.platform === "win32" ? null : "SIGABRT",
|
||||
},
|
||||
captured_output: {
|
||||
stderr: expect.stringContaining("heap out of memory"),
|
||||
|
||||
Reference in new issue
Block a user