@ai-sdk/workflow breaks workflow bundling on Nitro/Nuxt: Dynamic require of "ajv/dist/core.js" is not supported
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 2.4k
- Forks
- 365
- Avg merge
- 2d 11h
- Merged PRs (30d)
- 169
Description
Description
Importing @ai-sdk/workflow anywhere in a project that uses workflow/nitro (via workflow/nuxt) breaks the workflow steps bundle for every workflow in the project — including workflows that have nothing to do with @ai-sdk/workflow.
The root cause is a transitive dependency: @ai-sdk/workflow depends on ajv (confirmed via pnpm why ajv). ajv is CommonJS and uses a non-statically-analyzable require() internally to load ajv/dist/core.js. When workflow/nitro's esbuild step bundles the workflow steps as ESM, it can't resolve this dynamic require(), and generates a shim that throws at runtime instead of failing at build time.
Because the steps bundle (.nuxt/workflow/steps.mjs) is built from every file in the project containing a 'use workflow'/'use step' directive — not scoped to files that are actually reachable/used — a single unrelated file importing @ai-sdk/workflow (even an unused prototype file sitting outside server/) poisons the shared bundle for all workflows.
Environment
@ai-sdk/workflow: 1.0.31workflow/@workflow/core: 4.6.0- Nuxt: 4.5.0
- Nitro: 2.13.4
- Vite: 8.1.5
- Node: v24.18.0
- Package manager: pnpm
ajv: 8.20.0 (pulled in transitively by@ai-sdk/workflow)
Steps to Reproduce
-
Create a Nuxt project with
workflow/nuxtconfigured (modules: ["workflow/nuxt"]). -
Create a minimal workflow that does not use
@ai-sdk/workflowat all:// server/workflows/echo-test.ts export async function echoTest(items: string[]) { 'use workflow' return { received: items, count: items.length } }// server/api/echo-test.post.ts import { start } from 'workflow/api' import { echoTest } from '../workflow/echo-test' export default defineEventHandler(async (event) => { const body = await readBody(event) const run = await start(echoTest, [body.items ?? ['a', 'b', 'c']]) return await run.returnValue }) -
Confirm this works fine on its own —
curl -X POST http://localhost:3000/api/echo-test -d '{"items":["x","y","z"]}'returns{"received":["x","y","z"],"count":3}. -
Anywhere else in the project (any file, any directory — doesn't need to be imported/used by anything), add a file with
'use workflow'that imports@ai-sdk/workflow:import { WorkflowAgent } from '@ai-sdk/workflow' export async function chat(messages: any[]) { 'use workflow' // ... } -
Restart the dev server (
rm -rf .nuxt .output && pnpm devto rule out cache). -
Repeat the
curlfrom step 3 againstecho-testagain.
Expected Behavior
The echoTest workflow should keep working exactly as before — it has no relationship to @ai-sdk/workflow or ajv.
Actual Behavior
The request to echo-test fails with:
ERROR [request error] [unhandled] [POST] http://localhost:3000/.well-known/workflow/v1/flow
Error: Dynamic require of "../../node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/core.js" is not supported
at (.nuxt/workflow/steps.mjs:15:9)
at node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/ajv.js (.nuxt/workflow/steps.mjs:49:18)
at __require2 (.nuxt/workflow/steps.mjs:19:52)
...
ERROR [world-local] Queue message failed (attempt 1, HTTP 500) { queueName: '__wkf_workflow_workflow//./server/workflows/echo-test//echoTest', ... }
Removing the @ai-sdk/workflow import (and the package itself, confirmed via pnpm remove @ai-sdk/workflow + full node_modules reinstall) makes the error disappear completely and echo-test returns clean output again. Workflow count in the build log also drops (e.g. from 3 workflows to 2 workflows), confirming the unrelated file was being scanned and bundled in.
Additional Notes
- This reproduced consistently across multiple dev server restarts with
.nuxt/.outputcleared, so it is not a hot-reload/timing issue. - This may be related to the broader class of CJS/ESM interop bugs already tracked in this repo:
- #140 — bundler fails to resolve Node.js built-ins (
stream,http, etc.), treating them as browser externals - #258 —
ERR_REQUIRE_ESMwith@workflow/world-postgreson Next.js App Router
- #140 — bundler fails to resolve Node.js built-ins (
- Two separate concerns worth splitting if useful:
ajv's dynamicrequire()isn't handled correctly by the esbuild step-bundling pass (likely needsajvmarked external, or the step bundler needs a CJS-compatible require shim for cases like this).- The step/workflow bundler appears to scan the whole project (or at least beyond the configured
serverDir) for'use workflow'/'use step'directives, rather than only files actually reachable from used entry points — meaning dead/unused files can silently poison the shared bundle for unrelated workflows.
Minimal Reproduction
Happy to share a minimal repo if useful — the repro above is ~15 lines of code across 3 files.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing with workflow/nuxt using server/workflows/echo-test.ts and server/api/echo-test.post.ts, then inspect the generated .nuxt/workflow/steps.mjs and the workflow/nitro bundling path. Compare builds with and without the @ai-sdk/workflow import and determine whether the fix belongs in handling ajv's dynamic require or in scanning unrelated workflow files. Done means echo-test works despite the unrelated import.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- node.js, nuxt, typescript, vite
- Domain
- backend, build-system
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100