heygen-com/hyperframes · error · Error

Engine config hdr must be false or an hlg/pq transfer object

Error message

Engine config hdr must be false or an hlg/pq transfer object

What it means

validateEngineConfigHdr() requires `hdr` to be either the literal `false` or a single-key object `{ transfer: "hlg" | "pq" }` — the two HDR transfer functions the encode pipeline supports. Any other shape (true, a string, an object with extra keys, an object whose transfer is neither hlg nor pq) is rejected.

Source

Thrown at packages/engine/src/config.ts:481

    if (typeof config[field] !== "boolean")
      throw new Error(`Engine config ${field} must be a boolean`);
  }
  for (const field of POSITIVE_NUMBER_ENGINE_CONFIG_FIELDS) {
    assertEngineConfigNumber(config, field, 1, field === "frameDataUriCacheLimit");
  }
  assertEngineConfigNumber(config, "streamingEncodeMaxDurationSeconds", 0);
  assertEngineConfigNumber(config, "audioGain", 0);
}

function validateEngineConfigHdr(config: Record<string, unknown>): void {
  const { hdr } = config;
  if (
    hdr !== false &&
    (!isPlainObject(hdr) ||
      Object.keys(hdr).length !== 1 ||
      (hdr.transfer !== "hlg" && hdr.transfer !== "pq"))
  ) {
    throw new Error("Engine config hdr must be false or an hlg/pq transfer object");
  }
}

function validateOptionalEngineConfigFields(config: Record<string, unknown>): void {
  for (const field of ["chromePath", "runtimeManifestPath", "extractCacheDir"] as const) {
    if (
      config[field] !== undefined &&
      (typeof config[field] !== "string" || config[field].length === 0)
    ) {
      throw new Error(`Engine config ${field} must be a non-empty string`);
    }
  }
  if (config.expectedChromiumMajor !== undefined) {
    assertEngineConfigNumber(config, "expectedChromiumMajor", 1, true);
  }
  for (const field of [
    "pageSideCompositingAutoDisabled",
    "forceScreenshotExplicitlyOptedOut",

View on GitHub (pinned to c2996c8626)

Solutions

  1. For SDR, set hdr: false (the default).
  2. For HLG HDR, set hdr: { transfer: "hlg" }; for PQ, set hdr: { transfer: "pq" } — and no other keys.
  3. If you only need to detect HDR from source, that is `hdrAutoDetect` (a boolean), not `hdr`.

Example fix

// before
const snap = { ...DEFAULT_CONFIG, hdr: true };

// after
const snap = { ...DEFAULT_CONFIG, hdr: { transfer: "pq" } };
Defensive patterns

Strategy: type-guard

Validate before calling

function assertHdr(value: unknown): asserts value is false | { transfer: "hlg" | "pq" } {
  if (value === false) return;
  if (
    typeof value !== "object" || value === null ||
    Object.keys(value).length !== 1 ||
    ((value as any).transfer !== "hlg" && (value as any).transfer !== "pq")
  ) {
    throw new Error('hdr must be false or { transfer: "hlg" | "pq" }');
  }
}

Type guard

function isValidHdr(value: unknown): value is false | { transfer: "hlg" | "pq" } {
  if (value === false) return true;
  if (typeof value !== "object" || value === null) return false;
  const keys = Object.keys(value);
  return keys.length === 1 && (value.transfer === "hlg" || value.transfer === "pq");
}

Try / catch

try { validateEngineConfigSnapshot(snapshot); }
catch (e) {
  if (/hdr must be/.test(String(e))) {
    snapshot.hdr = false; // SDR fallback
    validateEngineConfigSnapshot(snapshot);
  } else throw e;
}

Prevention

When it happens

Trigger: validateEngineConfigSnapshot() receives hdr: true (use {transfer:"hlg"} instead), hdr: "hlg" (must be an object), hdr: {transfer:"hlg", other:1} (must be exactly one key), or hdr: {transfer:"dolby"} (unsupported transfer).

Common situations: Treating hdr as a boolean toggle; an older schema where hdr was a different shape; passing extra metadata keys alongside transfer; authoring a transfer function the pipeline does not encode.

Related errors


AI-assisted analysis of heygen-com/hyperframes@c2996c8626 (2026-08-12). Data as JSON: /api/errors/1dc57b2523a0a2ee. Report an issue: GitHub.