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: ${err instanceof Error ? err.message : String(err)}

What it means

Thrown as an InvalidConfigError by validateStepFunctionsInputSize when JSON.stringify(input) throws — meaning the Step Functions execution input contains a value that is not JSON-serializable. The most common cause is config.variables holding a circular reference, a BigInt, a function, or a Symbol-keyed structure. validateStepFunctionsInputSize is called by renderToLambda after assembling { ProjectS3Uri, Config, … } so the offending value is typically inside Config (the variables map). Catching it here surfaces the cause at the SDK boundary instead of as an opaque serialization failure inside the SFN wire layer.

Source

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

/**
 * Validate that the serialized Step Functions execution input fits inside the
 * 256 KiB Standard-workflow cap. Measured in UTF-8 bytes (the format Step
 * Functions uses on the wire) — JS strings count UTF-16 code units, which
 * under-reports for any multi-byte character.
 *
 * 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 ` +

View on GitHub (pinned to c2996c8626)

Solutions

  1. Inspect config.variables for non-JSON values: replace Date objects with .toISOString(), BigInt with String(), class instances with plain objects.
  2. Break circular references before the call (e.g. structuredClone with a replacer, or JSON.stringify with a custom replacer that detects cycles).
  3. Run JSON.stringify(JSON.parse(JSON.stringify(vars))) as a sanitization pre-step if the data is mostly-plain.
  4. Add a unit test that serializes the variables you intend to send.

Example fix

// before
config.variables = { user, req }; // req is circular

// after
config.variables = { userId: user.id, path: req.path }; // plain values only
Defensive patterns

Strategy: validation

Validate before calling

function assertSerializable(value: unknown): void {
  try {
    JSON.stringify(value);
  } catch (err) {
    throw new Error(`input is not JSON-serializable: ${(err as Error).message}`);
  }
}
// call before validateStepFunctionsInputSize / renderToLambda

Type guard

const isPlainJsonValue = (v: unknown): boolean => {
  if (v === null || typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean') return true;
  if (Array.isArray(v)) return v.every(isPlainJsonValue);
  if (typeof v === 'object') return Object.values(v).every(isPlainJsonValue);
  return false;
};

Prevention

When it happens

Trigger: config.variables includes a circular object (e.g. a DOM node or a class instance with back-references); a BigInt value; a function reference; a Symbol. The stringify of the whole input object throws.

Common situations: Passing a class instance (a Date subclass, a Moment object) instead of an ISO string; a variables map that includes the request/response object itself; a BigInt counter; an object with a self-referential parent pointer.

Related errors


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