mastra-ai/mastra · error · HTTPException

Invalid createdAt

Error message

Invalid createdAt

What it means

Thrown with HTTP 400 when an incoming workflow event's `createdAt` cannot be parsed into a valid Date. The route coerces the wire-format string timestamp to a Date before handing the event to `mastra.handleWorkflowEvent`; an unparsable value means the payload's timestamp field is malformed.

Source

Thrown at packages/server/src/server/handlers/workflows.ts:1616

  bodySchema: receiveWorkflowEventBodySchema,
  responseSchema: receiveWorkflowEventResponseSchema,
  summary: 'Receive a workflow event from a push-mode broker',
  description:
    'Push-mode entry point for workflow events. Brokers (GCP Pub/Sub push, SNS, EventBridge) POST each event here; Mastra processes it through the same pipeline as pull-mode workers.',
  tags: ['Workflows', 'Worker'],
  requiresAuth: true,
  // Broker push endpoint: it advances runtime state rather than editing
  // definitions, so `workflows:execute` is the more accurate fit. `write` is
  // kept for back-compat with service principals that already grant it.
  requiresPermission: ['workflows:write', 'workflows:execute'],
  handler: (async ({ mastra, event }: ReceiveWorkflowEventHandlerArgs) => {
    try {
      // The wire schema carries `createdAt` as a string; coerce to Date here
      // before handing off to the in-process pipeline, which expects an `Event`.
      const rawCreatedAt = (event as unknown as { createdAt: unknown }).createdAt;
      const createdAt = rawCreatedAt instanceof Date ? rawCreatedAt : new Date(rawCreatedAt as string);
      if (Number.isNaN(createdAt.getTime())) {
        throw new HTTPException(400, { message: 'Invalid createdAt' });
      }
      return await mastra.handleWorkflowEvent({ ...event, createdAt });
    } catch (error) {
      return handleError(error, 'Error receiving workflow event');
    }
  }) as any,
});

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Send `createdAt` as an ISO 8601 string (e.g. new Date().toISOString())
  2. Send a Date-serializable value or omit the field only if your version allows it
  3. Validate the timestamp parses before POSTing the event

Example fix

// before
body: { ...event, createdAt: String(Date.now()) }
// after
body: { ...event, createdAt: new Date().toISOString() }
Defensive patterns

Strategy: validation

Validate before calling

const d = new Date(event.createdAt); if (Number.isNaN(d.getTime())) throw new Error(`Invalid createdAt: ${event.createdAt}`);

Type guard

const isValidDateInput = (v: unknown): v is string | Date => typeof v === 'string' ? !Number.isNaN(new Date(v).getTime()) : v instanceof Date && !Number.isNaN(v.getTime());

Try / catch

try { await postWorkflowEvent(event); } catch (e) { if (isHttpException(e, 400) && /createdAt/.test(e.message)) console.error('Fix event.createdAt to ISO 8601', event.createdAt); else throw e; }

Prevention

When it happens

Trigger: POSTing a workflow event whose `createdAt` is undefined, an empty string, or a non-ISO string that `new Date(...)` cannot parse; producers emitting epoch numbers or locale-formatted dates.

Common situations: Custom producers emitting timestamps without toISOString(); forgetting to set createdAt when forwarding events; time libraries serializing with non-ISO formats.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/8974fa212e409e6a. Report an issue: GitHub.