heygen-com/hyperframes · error · InvalidConfigError

[validateConfig] config: Step Functions execution input is n

Error message

[validateConfig] config: Step Functions execution input is not JSON-serializable (JSON.stringify returned undefined). Check that all fields, including config.variables, are plain JSON values.

What it means

Thrown as an InvalidConfigError by validateStepFunctionsInputSize when JSON.stringify(input) returns undefined rather than throwing. Per the JS spec, JSON.stringify returns undefined (not throws) when the top-level value is a function, a Symbol, or undefined itself. This is distinct from error 50 (which fires when stringify throws on nested bad values). The message points specifically at config.variables because that is the usual source of a top-level non-serializable value when the input wrapper is assembled.

Source

Thrown at packages/aws-lambda/src/sdk/validateConfig.ts:61

 * Throws {@link InvalidConfigError} with a clear message naming the actual
 * byte count, the cap, and a pointer to the "working with large variables"
 * docs section, so users hit the limit at the SDK boundary with actionable
 * guidance instead of as a `States.DataLimitExceeded` 50 ms into the
 * execution.
 */
// fallow-ignore-next-line complexity
export function validateStepFunctionsInputSize(input: unknown): void {
  let serialized: string | undefined;
  try {
    serialized = JSON.stringify(input);
  } catch (err) {
    throw new InvalidConfigError(
      "config",
      `Step Functions execution input is not JSON-serializable: ${err instanceof Error ? err.message : String(err)}`,
    );
  }
  if (serialized === undefined) {
    throw new InvalidConfigError(
      "config",
      "Step Functions execution input is not JSON-serializable (JSON.stringify returned undefined). " +
        "Check that all fields, including config.variables, are plain JSON values.",
    );
  }
  const byteLength = Buffer.byteLength(serialized, "utf8");
  if (byteLength > MAX_STEP_FUNCTIONS_INPUT_BYTES) {
    throw new InvalidConfigError(
      "config",
      `Step Functions execution input is ${byteLength} bytes, which exceeds the ` +
        `${MAX_STEP_FUNCTIONS_INPUT_BYTES}-byte (256 KiB) limit for Standard workflows. ` +
        `Variables are for typed data (strings, numbers, structured records); media assets ` +
        `(images, audio, video) should be passed as URL references the composition resolves ` +
        `at render time, not inlined as base64. See ${LARGE_VARIABLES_DOCS_URL} for the ` +
        `URL-your-assets convention.`,
    );
  }
}

View on GitHub (pinned to c2996c8626)

Solutions

  1. Ensure the object passed to validateStepFunctionsInputSize is a plain object literal, not a function/Symbol/undefined.
  2. Confirm config.variables is an object (Record<string, …>), not undefined or a function reference.
  3. Add a typeof input === 'object' && input !== null guard before validation.
  4. Log the input's type before the call to spot a function/Symbol top-level.

Example fix

// before
validateStepFunctionsInputSize(config.variables?.toString);
// toString is a function -> stringify returns undefined

// after
validateStepFunctionsInputSize({ ...input, Config: { ...config, variables: vars } });
Defensive patterns

Strategy: validation

Validate before calling

function assertPlainObjectInput(input: unknown): asserts input is Record<string, unknown> {
  if (input === undefined || input === null || typeof input !== 'object' || Array.isArray(input)) {
    throw new Error('Step Functions input must be a plain object');
  }
  const serialized = JSON.stringify(input);
  if (serialized === undefined) throw new Error('input serializes to undefined');
}

Type guard

const isSerializableObject = (v: unknown): boolean => {
  if (v === null || typeof v !== 'object' || Array.isArray(v)) return false;
  return JSON.stringify(v) !== undefined;
};

Prevention

When it happens

Trigger: The entire input object, or the value fed to stringify, is a function or Symbol; config.variables was set to a function or undefined instead of an object. Less common than error 50 because the wrapper { ProjectS3Uri, Config, … } is normally a plain object — this fires when the wrapper itself is replaced or when a custom serializer is in play.

Common situations: A middleware that replaces the input with a function; config.variables assigned to undefined explicitly; a Symbol used as the top-level input; a bug where input = someFunction instead of input = { Config: someFunction }.

Related errors


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