Files
hyperframes/packages/producer/src/utils/errorMessage.test.ts
T
Miguel Ángel d83a873986 fix(producer): normalize error messages to prevent [object Object] in telemetry (#1099)
* fix(producer): normalize error messages to prevent [object Object] in telemetry

When a render fails and the caught value is a plain object (not an Error
instance), String(error) produces [object Object], masking the real error
in PostHog telemetry (~24 errors/day).

Add normalizeErrorMessage() that tries Error.message, string passthrough,
.message on plain objects, JSON.stringify, and String() as a last resort.
Apply it on the two telemetry-feeding paths: the main render failure
handler (renderOrchestrator.ts:2099) and buildRenderErrorDetails
(cleanup.ts), plus the error classifier isRecoverableParallelCaptureError
so timeout detection works even when the thrown value is a plain object.

* fix: address review — normalize CLI telemetry path, captureCost fallback

* fix: use local normalizeErrorMessage in CLI to avoid cross-package resolution

The Vite test runner can't resolve runtime imports from @hyperframes/producer
since its exports point to dist/. Copy the utility into the CLI package and
import locally instead.
2026-05-27 20:19:53 -04:00

44 lines
1.3 KiB
TypeScript

import { describe, it, expect } from "vitest";
import { normalizeErrorMessage } from "./errorMessage.js";
describe("normalizeErrorMessage", () => {
it("extracts message from Error instances", () => {
expect(normalizeErrorMessage(new Error("boom"))).toBe("boom");
});
it("passes through strings", () => {
expect(normalizeErrorMessage("oops")).toBe("oops");
});
it("extracts .message from plain objects", () => {
expect(normalizeErrorMessage({ message: "hidden error" })).toBe("hidden error");
});
it("JSON-stringifies objects without .message", () => {
expect(normalizeErrorMessage({ code: 42 })).toBe('{"code":42}');
});
it("handles null", () => {
expect(normalizeErrorMessage(null)).toBe("unknown error");
});
it("handles undefined", () => {
expect(normalizeErrorMessage(undefined)).toBe("unknown error");
});
it("handles numbers", () => {
expect(normalizeErrorMessage(42)).toBe("42");
});
it("handles objects with non-string .message", () => {
expect(normalizeErrorMessage({ message: 123 })).toBe('{"message":123}');
});
it("handles circular references gracefully", () => {
const obj: Record<string, unknown> = {};
obj.self = obj;
// Falls through JSON.stringify failure to Object.keys()
expect(normalizeErrorMessage(obj)).toBe("{self}");
});
});