Skip to content

Vercel World Regression: getWorkflowMetadata() fully breaking runs #1577

@pablodecm

Description

@pablodecm

Summary

workflow@4.2.0-beta.74 breaks multiple of our real Next.js workflow flows in the Vercel world.

The same flow works in:

  • workflow@4.2.0-beta.72

and fails in:

  • workflow@4.2.0-beta.74

The failure happens inside a valid "use step" function that calls getWorkflowMetadata() / getStepMetadata().

The exact error we get on Vercel is:

getWorkflowMetadata() can only be called inside a workflow or step function

What is important here is:

  • this is a real flow in our app, not just a synthetic test
  • the same flow works on beta.72
  • the same reduced repro works for us in local Next world
  • it fails in Vercel world on beta.74

So from our side this looks like a regression in beta.74, specifically in the Vercel world execution path.

Versions

  • next: 16.2.1
  • node: 24.x
  • working: workflow@4.2.0-beta.72
  • broken: workflow@4.2.0-beta.74

Minimal (AI) repro

We reduced it to this workflow:

import { getStepMetadata, getWorkflowMetadata } from "workflow";

export interface MetadataContextReproInput {
  label?: string;
}

export interface MetadataContextReproResult {
  label: string;
  workflowRunId: string;
  workflowStartedAt: string;
  stepId: string;
  attempt: number;
  stepStartedAt: string;
}

const withStrictMetadataCheck = async <T>(fn: () => Promise<T>) => {
  const workflowMetadata = getWorkflowMetadata();
  const stepMetadata = getStepMetadata();

  return await fn().then((result) => ({
    result,
    workflowMetadata,
    stepMetadata,
  }));
};

const metadataContextReproStep = async ({
  label = "metadata-context-repro",
}: MetadataContextReproInput): Promise<MetadataContextReproResult> => {
  "use step";

  const { workflowMetadata, stepMetadata } = await withStrictMetadataCheck(async () => label);

  return {
    label,
    workflowRunId: workflowMetadata.workflowRunId,
    workflowStartedAt: workflowMetadata.workflowStartedAt.toISOString(),
    stepId: stepMetadata.stepId,
    attempt: stepMetadata.attempt,
    stepStartedAt: stepMetadata.stepStartedAt.toISOString(),
  };
};

export const metadataContextReproWorkflow = async (
  input: MetadataContextReproInput,
): Promise<MetadataContextReproResult> => {
  "use workflow";

  return await metadataContextReproStep(input);
};

And this route:

import { start } from "workflow/api";
import { metadataContextReproWorkflow } from "@/server/lib/workflow/repros/metadata-context-repro.workflow";

export const POST = async (request: Request) => {
  const body = await request.json().catch(() => ({}));

  try {
    const run = await start(metadataContextReproWorkflow, [
      {
        label: typeof body.label === "string" && body.label.length > 0 ? body.label : undefined,
      },
    ]);

    const result = await run.returnValue;

    return Response.json({
      ok: true,
      result,
    });
  } catch (error) {
    return Response.json(
      {
        ok: false,
        error: error instanceof Error ? error.message : String(error),
        stack: error instanceof Error ? error.stack : undefined,
      },
      { status: 500 },
    );
  }
};

That can be triggered with:

curl -X POST https://<deployment>/api/workflow-metadata-repro \
  -H 'content-type: application/json' \
  -d '{"label":"smoke-test"}'

Actual behavior on Vercel with 4.2.0-beta.74:
This is the exact response we get:

{
  "ok": false,
  "error": "Workflow run \"wrun_01KN46H2XC7V3WRECB61EZ4SKJ\" failed: Step \"step//./src/server/lib/workflow/repros/metadata-context-repro.workflow//metadataContextReproStep\" failed after 3 retries: `getWorkflowMetadata()` can only be called inside a workflow or step function"
}

The stack includes:

Caused by: Error: `getWorkflowMetadata()` can only be called inside a workflow or step function
    at ...
    at withStrictMetadataCheck (...)
    at metadataContextReproStep (...)

So this is definitely being thrown from inside metadataContextReproStep, which is a valid "use step" function.

Repro matrix

  • workflow@4.2.0-beta.72 + Vercel world: works
  • workflow@4.2.0-beta.74 + Vercel world: fails
  • workflow@4.2.0-beta.74 + local Next world: works

Why this looks like a framework regression

This does not look like invalid API usage because:

  • getWorkflowMetadata() / getStepMetadata() are called inside a valid "use step"
  • they are not called at module top level
  • the same real flow works on beta.72
  • the same reduced repro works locally
  • the failure is specific to Vercel world on beta.74

Possible relation

I am not certain about root cause, but this may be related to recent builder/runtime regressions in the same version window.

A few upstream items that looked relevant while investigating:

I do not want to overstate this, since this specific repro is in Vercel world and not necessarily the exact same bug. But the failure mode looks similar: metadata helpers behaving as if step context is missing inside a valid step.

Possibly relevant detail

In this repro, "use workflow" and "use step" are in the same file. I am not sure whether that is required to trigger the issue, but it may be relevant.

Question

Is there a known regression between 4.2.0-beta.72 and 4.2.0-beta.74 in the Vercel world that could cause step metadata context to be missing inside a valid "use step"?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions