heygen-com/hyperframes · error · Error

[handler] unknown Action: ${JSON.stringify((_exhaustive as {

Error message

[handler] unknown Action: ${JSON.stringify((_exhaustive as { Action?: string }).Action)}. Expected one of "plan", "renderChunk", "assemble".

What it means

Thrown by the Lambda handler's action dispatch when the `Action` field does not match any of `plan`, `renderChunk`, `assemble`. The `default` branch assigns the event to a `never`-typed variable so a new `LambdaAction` member breaks compilation before this runtime error is reachable — it is the exhaustiveness guard for the discriminated union.

Source

Thrown at packages/aws-lambda/src/handler.ts:118

  validateEventS3Uris(unwrapped);
  primeRuntimeEnv();
  // Single structured boot log line — CloudWatch Logs Insights queries
  // key off `event=handler_start` to grep for a specific Action / S3 URI
  // when triaging without attaching a debugger.
  logEvent({ event: "handler_start", action: unwrapped.Action, input: summarizeEvent(unwrapped) });
  try {
    switch (unwrapped.Action) {
      case "plan":
        return await handlePlan(unwrapped, deps);
      case "renderChunk":
        return await handleRenderChunk(unwrapped, deps);
      case "assemble":
        return await handleAssemble(unwrapped, deps);
      default: {
        // Compile-time exhaustiveness: a new LambdaAction member trips
        // the `never` assignment before the runtime error is reachable.
        const _exhaustive: never = unwrapped;
        throw new Error(
          `[handler] unknown Action: ${JSON.stringify(
            (_exhaustive as { Action?: string }).Action,
          )}. Expected one of "plan", "renderChunk", "assemble".`,
        );
      }
    }
  } catch (err) {
    normalizeTerminalErrorName(err);
    // Log before re-throwing so CloudWatch captures the structured
    // error context alongside Lambda's default stack trace. Otherwise
    // ops only sees the trace and has to correlate with execution
    // history to recover the action + input.
    logEvent({
      event: "handler_error",
      action: unwrapped.Action,
      input: summarizeEvent(unwrapped),
      message: err instanceof Error ? err.message : String(err),
      name: err instanceof Error ? err.name : undefined,

View on GitHub (pinned to c2996c8626)

Solutions

  1. Align caller and Lambda versions — send only `plan`, `renderChunk`, or `assemble`.
  2. If you added a new LambdaAction variant, add its case to the switch (the `never` assignment will have already failed the build).
  3. Inspect the `Action` value printed in the message and fix the caller's payload.
  4. Redeploy the Lambda so its supported actions match the producer.

Example fix

// before: producer emits unsupported action
{ Action: "planV2", ... }
// after
{ Action: "plan", ... }
Defensive patterns

Strategy: type-guard

Type guard

const LAMBDA_ACTIONS = new Set(["plan", "renderChunk", "assemble"]);
function isLambdaAction(value: unknown): value is "plan" | "renderChunk" | "assemble" {
  return typeof value === "string" && LAMBDA_ACTIONS.has(value);
}

Try / catch

try {
  return await dispatch(unwrapped, deps);
} catch (err) {
  if (err instanceof Error && err.message.startsWith("[handler] unknown Action")) {
    // caller version skew — reject the payload with a 4xx-shaped error
  }
  throw err;
}

Prevention

When it happens

Trigger: An event reaches the dispatch switch with an `Action` value other than the three known ones — either an unknown action was sent, or a new action variant was added to the union without a handler case.

Common situations: Caller sends `Action: "planV2"` or some future action the handler doesn't yet support; a producer/CLI version skew where the client emits actions this Lambda version doesn't recognize; malformed test fixtures.

Related errors


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