heygen-com/hyperframes · error · Error

Engine config ${field} must be a ${integer ? "finite integer

Error message

Engine config ${field} must be a ${integer ? "finite integer" : "finite number"} >= ${min}

What it means

assertEngineConfigNumber() validates a numeric engine-config field has a finite value at or above a minimum (and is an integer when the field demands it). It is applied to jpegQuality (>=0), minParallelFrames & largeRenderThreshold (>=0, integer), streamingEncodeMaxDurationSeconds & audioGain (>=0), the POSITIVE_NUMBER fields like timeouts/chunkSizeFrames (>=1), frameDataUriCacheLimit (>=1, integer), and expectedChromiumMajor (>=1, integer when present).

Source

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

    !Array.isArray(value) &&
    [Object.prototype, null].includes(Object.getPrototypeOf(value))
  );
}

function assertEngineConfigNumber(
  config: Record<string, unknown>,
  field: string,
  min: number,
  integer = false,
): void {
  const value = config[field];
  if (
    typeof value !== "number" ||
    !Number.isFinite(value) ||
    value < min ||
    (integer && !Number.isInteger(value))
  ) {
    throw new Error(
      `Engine config ${field} must be a ${integer ? "finite integer" : "finite number"} >= ${min}`,
    );
  }
}

function assertPositiveEngineConfigNumber(config: Record<string, unknown>, field: string): void {
  const value = config[field];
  if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
    throw new Error(`Engine config ${field} must be a finite number > 0`);
  }
}

function assertEngineConfigEnum(
  config: Record<string, unknown>,
  field: string,
  values: readonly unknown[],
): void {
  if (!values.includes(config[field])) throw new Error(`Engine config ${field} is invalid`);

View on GitHub (pinned to c2996c8626)

Solutions

  1. Read the field name and the required minimum in the message, then set that field in the snapshot to a finite number at/above the minimum.
  2. For integer fields (minParallelFrames, largeRenderThreshold, frameDataUriCacheLimit, expectedChromiumMajor) ensure the value has no fractional part.
  3. Prefer building the snapshot via resolveConfig() (which fills defaults) rather than hand-authoring JSON.
  4. Validate the snapshot with validateEngineConfigSnapshot() during development to catch the field before it reaches the wire.

Example fix

// before
const snapshot = { ...DEFAULT_CONFIG, browserTimeout: 0, chunkSizeFrames: 1.5 };
validateEngineConfigSnapshot(snapshot); // throws on browserTimeout

// after
const snapshot = { ...DEFAULT_CONFIG, browserTimeout: 60_000, chunkSizeFrames: 360 };
validateEngineConfigSnapshot(snapshot);
Defensive patterns

Strategy: validation

Validate before calling

function assertNumericField(field: string, value: unknown, min: number, integer = false): void {
  if (typeof value !== "number" || !Number.isFinite(value) || value < min) {
    throw new Error(`${field} must be a finite number >= ${min}`);
  }
  if (integer && !Number.isInteger(value)) {
    throw new Error(`${field} must be an integer >= ${min}`);
  }
}

// call before validateEngineConfigSnapshot for clear errors:
assertNumericField("browserTimeout", cfg.browserTimeout, 1);
assertNumericField("chunkSizeFrames", cfg.chunkSizeFrames, 1, true);

Type guard

function isFiniteNumberAtLeast(value: unknown, min: number, integer = false): boolean {
  return typeof value === "number"
    && Number.isFinite(value)
    && value >= min
    && (!integer || Number.isInteger(value));
}

Try / catch

try {
  validateEngineConfigSnapshot(snapshot);
} catch (e) {
  if (/Engine config .* must be a .* number/.test(String(e))) {
    throw new Error(`Rejecting render request: ${e.message}`, { cause: e });
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling validateEngineConfigSnapshot(value) — i.e. crossing a JSON wire boundary such as a serialized render request — with one of those fields set to a string, NaN/Infinity, a negative number, a float where an integer is required, or below the field's minimum (e.g. `jpegQuality: -5`, `browserTimeout: 0`, `chunkSizeFrames: 1.5`).

Common situations: Hand-editing a serialized render config; a stale client sending an old schema; env-var override misparsed to a string; JSON deserialization of a config that was never run through resolveConfig(); passing a partial snapshot that skipped orchestrator defaults.

Related errors


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