mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-10-30 17:27:09 +00:00
fix(cli): a failed render's code comes only from the producer's list of safe codes (#6737)
This commit is contained in:
@@ -108,9 +108,12 @@ describe("render diagnostic wire", () => {
|
||||
"AUDIO_PROCESSING_FAILED",
|
||||
],
|
||||
[
|
||||
new Error(`Video extraction failed [VIDEO_SOURCE_UNRENDERABLE; source_missing=1] ${PRIVATE}`),
|
||||
Object.assign(new Error(`Video extraction failed ${PRIVATE}`), {
|
||||
code: "VIDEO_SOURCE_UNRENDERABLE",
|
||||
}),
|
||||
"VIDEO_SOURCE_UNRENDERABLE",
|
||||
],
|
||||
[new Error(`[HDR] No Chrome binary found [ACME_LAUNCH] ${PRIVATE}`), "RENDER_FAILED"],
|
||||
[
|
||||
Object.assign(new Error(`ENOENT: no such file, open '${PRIVATE}'`), { code: "ENOENT" }),
|
||||
"ENOENT",
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import { RenderQualityError, type RenderJob } from "@hyperframes/producer";
|
||||
import {
|
||||
RenderQualityError,
|
||||
extractSafeRenderErrorCode,
|
||||
type RenderJob,
|
||||
} from "@hyperframes/producer";
|
||||
import { CaptureFailure, audioFailureDiagnostics } from "@hyperframes/engine";
|
||||
|
||||
const FILE_ERRORS = [
|
||||
@@ -14,7 +18,6 @@ const FILE_ERRORS = [
|
||||
"EXDEV",
|
||||
];
|
||||
const FILE_ERROR = new RegExp(`\\b(${FILE_ERRORS.join("|")})\\b`);
|
||||
const CLI_CODE = /\[(?!(?:DEBUG|INFO|WARN|ERROR)\b)([A-Z][A-Z0-9_]{2,63})[\];]/;
|
||||
|
||||
function fileErrorOf(error: unknown, message: string): string | undefined {
|
||||
let seen: unknown = error;
|
||||
@@ -26,6 +29,16 @@ function fileErrorOf(error: unknown, message: string): string | undefined {
|
||||
return FILE_ERROR.exec(message)?.[1];
|
||||
}
|
||||
|
||||
function producerCodeOf(error: unknown): string | undefined {
|
||||
let seen: unknown = error;
|
||||
for (let depth = 0; depth < 5 && seen instanceof Error; depth++) {
|
||||
const code = extractSafeRenderErrorCode(seen);
|
||||
if (code) return code;
|
||||
seen = seen.cause;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function captureCodeOf(error: unknown, message: string): string | undefined {
|
||||
if (/Composition has zero duration/.test(message)) return "COMPOSITION_ZERO_DURATION";
|
||||
if (!(error instanceof CaptureFailure)) return undefined;
|
||||
@@ -38,7 +51,7 @@ function renderFailureCode(error: unknown): string {
|
||||
if (error instanceof RenderQualityError && error.warnings[0])
|
||||
return error.warnings[0].code.toUpperCase();
|
||||
return (
|
||||
CLI_CODE.exec(message)?.[1] ??
|
||||
producerCodeOf(error) ??
|
||||
fileErrorOf(error, message) ??
|
||||
captureCodeOf(error, message) ??
|
||||
"RENDER_FAILED"
|
||||
|
||||
@@ -24,6 +24,7 @@ export {
|
||||
type RenderPerfSummary,
|
||||
type ProgressCallback,
|
||||
} from "./services/renderOrchestrator.js";
|
||||
export { extractSafeRenderErrorCode } from "./services/safeRenderErrorCode.js";
|
||||
export {
|
||||
RENDER_JOB_DIR,
|
||||
createOwnedRenderDir,
|
||||
|
||||
@@ -51,6 +51,9 @@ import {
|
||||
} from "@hyperframes/core";
|
||||
import { parseEncoderOptions } from "@hyperframes/studio-server/encoder-options";
|
||||
import { createRenderRequest, renderConfigFromRequest } from "./renderRequest.js";
|
||||
import { extractSafeRenderErrorCode } from "./services/safeRenderErrorCode.js";
|
||||
|
||||
export { extractSafeRenderErrorCode };
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Types
|
||||
@@ -128,29 +131,6 @@ interface PreparedRenderInput {
|
||||
|
||||
const DEFAULT_SERVER_FPS = { num: 30, den: 1 } as const;
|
||||
const SSE_KEEPALIVE_MS = 30_000;
|
||||
const SAFE_RENDER_ERROR_CODES = new Set<string>([
|
||||
"ASSET_MEDIA_TYPE_MISMATCH",
|
||||
"HEIF_IMAGE_CONVERSION_FAILED",
|
||||
"HEIF_TOOL_UNAVAILABLE",
|
||||
"NOT_MEDIA_PAYLOAD",
|
||||
"INVALID_VIDEO_METADATA",
|
||||
"VIDEO_SOURCE_UNRENDERABLE",
|
||||
"VIDEO_EXTRACTION_FAILED",
|
||||
"ENCODER_INTERRUPTED",
|
||||
"RENDER_TOO_SLOW",
|
||||
"RENDER_STAGE_STALLED",
|
||||
]);
|
||||
|
||||
/**
|
||||
* Preserve only bounded producer error codes across JSON/SSE. Never derive a
|
||||
* code from the message: it may contain local paths or signed source URLs.
|
||||
*/
|
||||
export function extractSafeRenderErrorCode(error: unknown): string | undefined {
|
||||
if (typeof error !== "object" || error === null || !("code" in error)) return undefined;
|
||||
const code = error.code;
|
||||
return typeof code === "string" && SAFE_RENDER_ERROR_CODES.has(code) ? code : undefined;
|
||||
}
|
||||
|
||||
export interface SafeRenderErrorMetadata {
|
||||
errorCode: string;
|
||||
errorOwner?: "system" | "user";
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
const SAFE_RENDER_ERROR_CODES = new Set<string>([
|
||||
"ASSET_MEDIA_TYPE_MISMATCH",
|
||||
"HEIF_IMAGE_CONVERSION_FAILED",
|
||||
"HEIF_TOOL_UNAVAILABLE",
|
||||
"NOT_MEDIA_PAYLOAD",
|
||||
"INVALID_VIDEO_METADATA",
|
||||
"VIDEO_SOURCE_UNRENDERABLE",
|
||||
"VIDEO_EXTRACTION_FAILED",
|
||||
"ENCODER_INTERRUPTED",
|
||||
"RENDER_TOO_SLOW",
|
||||
"RENDER_STAGE_STALLED",
|
||||
]);
|
||||
|
||||
/**
|
||||
* Preserve only bounded producer error codes across JSON/SSE. Never derive a
|
||||
* code from the message: it may contain local paths or signed source URLs.
|
||||
*/
|
||||
export function extractSafeRenderErrorCode(error: unknown): string | undefined {
|
||||
if (typeof error !== "object" || error === null || !("code" in error)) return undefined;
|
||||
const code = error.code;
|
||||
return typeof code === "string" && SAFE_RENDER_ERROR_CODES.has(code) ? code : undefined;
|
||||
}
|
||||
Reference in New Issue
Block a user