TL;DR
@vercel/sandbox ships "use step" directives in its published dist. When a Next app using @workflow/next has the SDK anywhere in the module graph of /.well-known/workflow/v1/step, the workflow SWC plugin rewrites the SDK's classes — which are anonymous class expressions — and emits a reference to a binding that does not exist. The build fails during "Collecting page data".
Both packages are Vercel's, so this looks like an interop defect rather than a misuse.
Error
Error: Failed to collect configuration for /.well-known/workflow/v1/step
at ignore-listed frames {
[cause]: ReferenceError: AnonymousClass is not defined
at ../../node_modules/@vercel/sandbox/dist/filesystem.js (app/.well-known/workflow/v1/step/route.js:6207:84)
at <unknown> (app/.well-known/workflow/v1/step/route.js:10:54)
at module evaluation (app/.well-known/workflow/v1/step/route.js:11749:1)
6205 | }
6206 | };
> 6207 | registerStepFunction29("step//@vercel/sandbox@3.1.0//AnonymousClass#readFile", AnonymousClass.prototype["readFile"]);
| ^
6208 | registerStepFunction29("step//@vercel/sandbox@3.1.0//AnonymousClass#writeFile", AnonymousClass.prototype["writeFile"]);
6209 | registerStepFunction29("step//@vercel/sandbox@3.1.0//AnonymousClass#appendFile", AnonymousClass.prototype["appendFile"]);
6210 | registerStepFunction29("step//@vercel/sandbox@3.1.0//AnonymousClass#mkdir", AnonymousClass.prototype["mkdir"]);
}
> Build error occurred
Error: Failed to collect page data for /.well-known/workflow/v1/step
Suspected cause
@vercel/sandbox/dist/filesystem.js declares its classes as anonymous class expressions assigned to a variable:
var SandboxStats = class { … };
var SandboxDirent = class { … };
var FileSystem = class { … }; // 20 "use step" directives in this file
The loader transforms any file whose source carries a directive, including files under node_modules (@workflow/next/dist/loader.js, patterns.hasDirective). For a class expression the plugin appears to fall back to the placeholder name AnonymousClass instead of the variable the class is assigned to, then emits AnonymousClass.prototype["readFile"]. Nothing declares AnonymousClass, so the module throws on evaluation.
Using the assigned variable name (FileSystem), or skipping registration when no binding can be resolved, would both avoid this.
Reproduction
In a Next app with withWorkflow configured, import @vercel/sandbox from any module reachable from a "use step" function, then run next build. The failure is at "Collecting page data", not at compile.
Environment
@vercel/sandbox 3.1.0
@workflow/next 4.1.2
- next 16.3.1, Turbopack
- Node 24, pnpm 10.32.1, macOS arm64
Already ruled out
- Upgrading the SDK. 3.0.1, 3.1.0, 3.2.0 and 3.2.1 all ship
var FileSystem = class — verified by unpacking each tarball.
serverExternalPackages: ["@vercel/sandbox"]. Same failure; the loader rewrites the source before externalisation applies.
- A non-literal import specifier, to keep the SDK out of the graph. Turbopack folds the constant, then fails
Module not found: Can't resolve '@vercel/sandbox'.
- A
withWorkflow exclusion option. None found — the only documented option is workflows.local.port.
Questions
- Is a fix planned, and on which side — the SWC plugin's naming of class expressions, or the SDK's published dist shape?
- Is there a supported way to exclude a package from the workflow step transform?
Impact
We can only reach @vercel/sandbox from non-Next runtimes today; our Next app's workflow routes cannot use it at all. That blocks moving our sandbox workload onto Vercel Sandbox, since most of our code-execution entrypoints run inside workflow steps.
Possibly related, though both are different failure modes: #3051 (directive-free modules sent through SWC on the Nitro builder) and #3900 (valid use step directives missed after raw backticks). Both suggest the directive-detection and transform path is where this belongs.
TL;DR
@vercel/sandboxships"use step"directives in its publisheddist. When a Next app using@workflow/nexthas the SDK anywhere in the module graph of/.well-known/workflow/v1/step, the workflow SWC plugin rewrites the SDK's classes — which are anonymous class expressions — and emits a reference to a binding that does not exist. The build fails during "Collecting page data".Both packages are Vercel's, so this looks like an interop defect rather than a misuse.
Error
Suspected cause
@vercel/sandbox/dist/filesystem.jsdeclares its classes as anonymous class expressions assigned to a variable:The loader transforms any file whose source carries a directive, including files under
node_modules(@workflow/next/dist/loader.js,patterns.hasDirective). For a class expression the plugin appears to fall back to the placeholder nameAnonymousClassinstead of the variable the class is assigned to, then emitsAnonymousClass.prototype["readFile"]. Nothing declaresAnonymousClass, so the module throws on evaluation.Using the assigned variable name (
FileSystem), or skipping registration when no binding can be resolved, would both avoid this.Reproduction
In a Next app with
withWorkflowconfigured, import@vercel/sandboxfrom any module reachable from a"use step"function, then runnext build. The failure is at "Collecting page data", not at compile.Environment
@vercel/sandbox3.1.0@workflow/next4.1.2Already ruled out
var FileSystem = class— verified by unpacking each tarball.serverExternalPackages: ["@vercel/sandbox"]. Same failure; the loader rewrites the source before externalisation applies.Module not found: Can't resolve '@vercel/sandbox'.withWorkflowexclusion option. None found — the only documented option isworkflows.local.port.Questions
Impact
We can only reach
@vercel/sandboxfrom non-Next runtimes today; our Next app's workflow routes cannot use it at all. That blocks moving our sandbox workload onto Vercel Sandbox, since most of our code-execution entrypoints run inside workflow steps.Possibly related, though both are different failure modes: #3051 (directive-free modules sent through SWC on the Nitro builder) and #3900 (valid
use stepdirectives missed after raw backticks). Both suggest the directive-detection and transform path is where this belongs.