Dan @ Inngest
Dan @ Inngest2mo ago

Help with writing Inngest http action - dynamic Node require

Hi there, A user of our community asked about a Convex adapter for Inngest and when building it, it failed with the following error:
✘ [ERROR] Could not resolve "node:async_hooks"

node_modules/.pnpm/inngest@3.39.2_typescript@5.8.3/node_modules/inngest/components/execution/als.js:61:98:
61 │ ...st { AsyncLocalStorage } = await Promise.resolve().then(() => __importStar(require("node:async_hooks")));
╵ ~~~~~~~~~~~~~~~~~~

The package "node:async_hooks" wasn't found on the file system but is built into node. Are you
trying to bundle for node? You can use "platform: 'node'" to do that, which will remove this
error.

It looks like you are using Node APIs from a file without the "use node" directive.
Split out actions using Node.js APIs like this into a new file only containing actions that uses "use node" so these actions will run in a Node.js environment.
For more information see https://docs.convex.dev/functions/runtimes#nodejs-runtime
✘ [ERROR] Could not resolve "node:async_hooks"

node_modules/.pnpm/inngest@3.39.2_typescript@5.8.3/node_modules/inngest/components/execution/als.js:61:98:
61 │ ...st { AsyncLocalStorage } = await Promise.resolve().then(() => __importStar(require("node:async_hooks")));
╵ ~~~~~~~~~~~~~~~~~~

The package "node:async_hooks" wasn't found on the file system but is built into node. Are you
trying to bundle for node? You can use "platform: 'node'" to do that, which will remove this
error.

It looks like you are using Node APIs from a file without the "use node" directive.
Split out actions using Node.js APIs like this into a new file only containing actions that uses "use node" so these actions will run in a Node.js environment.
For more information see https://docs.convex.dev/functions/runtimes#nodejs-runtime
I attempted to: * Modify the Inngest source to add "use node" and it didn't work * Add "use node" in my convex/inngest.js http action file * Add "node": { "externalPackages": ["inngest"] } to my convex.json file None of the above worked, but I also saw something about Convex not supporting dynamic requires or imports at all. Is there a way to work around this or perhaps detect it in the Inngest package source code so it gracefully doesn't support this functionality? Sources: * Inngest source code for this import - It uses import in the source, but when transpiled for npm, it uses a require as seen in the error above. Thanks!
GitHub
inngest-js/packages/inngest/src/components/execution/als.ts at bf8a...
The developer platform for easily building reliable workflows with zero infrastructure for TypeScript & JavaScript - inngest/inngest-js
9 Replies
Convex Bot
Convex Bot2mo ago
Thanks for posting in <#1088161997662724167>. Reminder: If you have a Convex Pro account, use the Convex Dashboard to file support tickets. - Provide context: What are you trying to achieve, what is the end-user interaction, what are you seeing? (full error message, command output, etc.) - Use search.convex.dev to search Docs, Stack, and Discord all at once. - Additionally, you can post your questions in the Convex Community's <#1228095053885476985> channel to receive a response from AI. - Avoid tagging staff unless specifically instructed. Thank you!
ballingt
ballingt2mo ago
Hey @Dan @ Inngest, thanks for helping the customer debug! Do you have a repro by chance or could you point me to a good inngest starter?
Dan @ Inngest
Dan @ InngestOP2mo ago
Hey @ballingt - thanks for following up - here's the demo repo I just pushed: https://github.com/inngest/inngest-convex-test
GitHub
GitHub - inngest/inngest-convex-test
Contribute to inngest/inngest-convex-test development by creating an account on GitHub.
Dan @ Inngest
Dan @ InngestOP2mo ago
The inngest.ts code should work, but I wasn't able to test the httpAction due to the error. After installing the deps, I manually edited my node_modules to test the "use node" directive to see if that worked if we added it to our actual package code.
ballingt
ballingt2mo ago
I'll play with this and try to hook something up, something not clear here is that httpAction()s can't be defined in a "use node" file, if you need HTTP you'll have to make due with the generated HTTP API that every convex query, mutation, or action receives; or write the httpAction in a non-"use node" file and call await ctx.runAction(api.inngest.something, args); to invoke the defined in a "use node" file As written, the non-"use node" convex/http.ts file is importing the "use node" convex/inngest.ts, and there's no bundler funny business to help out here by turning this into RPC or something, that's a real import, so the inngest imports also end up in the convex/http.ts entry point If you want to use "use node" for some reason, here's an approach: https://github.com/inngest/inngest-convex-test/pull/1 Unfortunately streaming isn't going to work across the Convex JS runtime / Node.js JS runtime boundary, so ideally we could support Inngest running in the convex js runtime like you were trying to do initially. So we're bundling with esbuild, not marking node imports as external because we want them to fail the build since normally they're a mistake. One approach is hiding the import from esbuild, when I make change to packages/inngest/src/components/execution/als.ts it works with convex:
try {
const unbundleableNodeAsyncHooks = "node:async_hooks";
const { AsyncLocalStorage } = (await import(
unbundleableNodeAsyncHooks
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
)) as typeof import("node:async_hooks");

resolve(new AsyncLocalStorage<AsyncContext>());
} catch (err) {
try {
const unbundleableNodeAsyncHooks = "node:async_hooks";
const { AsyncLocalStorage } = (await import(
unbundleableNodeAsyncHooks
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
)) as typeof import("node:async_hooks");

resolve(new AsyncLocalStorage<AsyncContext>());
} catch (err) {
None of the above worked, but I also saw something about Convex not supporting dynamic requires or imports at all. Is there a way to work around this or perhaps detect it in the Inngest package source code so it gracefully doesn't support this functionality?
Yeah queries and mutations don't support dynamic imports in Convex, but actions do, it's just that these dynamic imports aren't making it through the series of bundlers; in this case convex invokes esbuild to bundle the inngest code which is a dynamic require (edit: as you point out in the thread title) rather than import in inngest bundle: https://app.unpkg.com/inngest@3.39.2/files/components/execution/als.js#L60-61
const { AsyncLocalStorage } = await Promise.resolve().then(() => __importStar(require("node:async_hooks")));
resolve(new AsyncLocalStorage());
const { AsyncLocalStorage } = await Promise.resolve().then(() => __importStar(require("node:async_hooks")));
resolve(new AsyncLocalStorage());
but this result is the same, esbuild is happy to try to bundle require("node:async_hooks") too
ballingt
ballingt2mo ago
GitHub
obscure "node:async_hooks" import from bundlers by thomasballinger ...
Summary Obscure the dynamic import of an optional Node.js dependency to prevent bundlers from attempting to inline the code. By preserving the intended runtime behavior this makes code bundled for ...
Dan @ Inngest
Dan @ InngestOP2mo ago
Hey @ballingt - I've been trying to test this PR change with my convex project and keep running into this issue:
Error fetching POST http://127.0.0.1:3210/api/push_config 400 Bad Request: DeploymentNotConfiguredForNodeActions: Hit an error while pushing:
Deployment is not configured to deploy "use node" actions. Node.js v18 is not installed. Install Node.js 18 with nvm (https://github.com/nvm-sh/nvm) to deploy Node.js actions.
Error fetching POST http://127.0.0.1:3210/api/push_config 400 Bad Request: DeploymentNotConfiguredForNodeActions: Hit an error while pushing:
Deployment is not configured to deploy "use node" actions. Node.js v18 is not installed. Install Node.js 18 with nvm (https://github.com/nvm-sh/nvm) to deploy Node.js actions.
I already ran nvm use 18 and that's installed, so I don't know what's failing here. Update - I think I solved it! Ok - now I still get this error:
Error : Dynamic require of "./als.import.cjs" is not supported
at <anonymous> (convex:/_deps/SKUECPGL.js:10:9)
at <anonymous> (../../node_modules/.pnpm/inngest@3.34.2-pr-931.4_typescript@5.8.3/node_modules/src/components/execution/als.ts:43:36)
Error : Dynamic require of "./als.import.cjs" is not supported
at <anonymous> (convex:/_deps/SKUECPGL.js:10:9)
at <anonymous> (../../node_modules/.pnpm/inngest@3.34.2-pr-931.4_typescript@5.8.3/node_modules/src/components/execution/als.ts:43:36)
It's working now!
Dan @ Inngest
Dan @ InngestOP2mo ago
GitHub
GitHub - inngest/inngest-convex-test
Contribute to inngest/inngest-convex-test development by creating an account on GitHub.
ballingt
ballingt2mo ago
@Dan @ Inngest beautiful, that's great, thanks for persevering! If you remember what you hit let us know, would love to make sure the self-hosting instructions are getting love.

Did you find this page helpful?