Skip to content

[bug] node:* bundled into main entrypoint breaks non-Node bundlers (Convex, etc.) #387

Description

@enisdenjo

evlog version

2.19.1

Runtime & OS

Convex 1.41.0

Framework / integration

Other

Adapter or drain (optional)

No response

Description

The main evlog entrypoint (dist/index.mjs) transitively imports dist/audit-BQt8yAHo.mjs, which contains:

  1. A dynamic import("node:crypto") fallback in getSubtle() for Node 18 where globalThis.crypto is not available by default
  2. A dynamic import("./pretty-error-snippet.node-itfCajBM.mjs") for disk-based error snippets, guarded at runtime by !isBrowser() && process.versions?.node

dist/pretty-error-snippet.node-itfCajBM.mjs has static top-level imports of node:module, node:path, and node:fs.

Both dynamic imports already have runtime guards, and node:crypto even has a /* @vite-ignore */ comment. However, bundlers that target non-Node runtimes (e.g. Convex's V8 runtime, Cloudflare Workers without compat flags) resolve all import() expressions statically during bundling - they don't evaluate runtime conditions. This causes hard build errors like:

Could not resolve "node:*"

The affected use case: defineErrorCatalog (and other exports from the main entrypoint) have zero dependency on any of these Node APIs. Users importing only error catalog utilities get dragged into Node-specific code they will never execute.

Expected behavior

npx convex dev succeeds

Actual behavior

npx convex dev fails with:

✘ [ERROR] Could not resolve "node:crypto"

    node_modules/.bun/evlog@2.19.1+83d5fd7b249dbeef/node_modules/evlog/dist/audit-BQt8yAHo.mjs:1874:2:
      1874 │     "node:crypto"
           ╵     ~~~~~~~~~~~~~

  The package "node:crypto" 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.

✘ [ERROR] Could not resolve "node:module"

    node_modules/.bun/evlog@2.19.1+83d5fd7b249dbeef/node_modules/evlog/dist/pretty-error-snippet.node-itfCajBM.mjs:2:7:
      2 │ import "node:module";
        ╵        ~~~~~~~~~~~~~

  The package "node:module" 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.

✘ [ERROR] Could not resolve "node:path"

    node_modules/.bun/evlog@2.19.1+83d5fd7b249dbeef/node_modules/evlog/dist/pretty-error-snippet.node-itfCajBM.mjs:3:24:
      3 │ import { resolve } from "node:path";
        ╵                         ~~~~~~~~~~~

                                                                                          The package "node:path" 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.
✘ [ERROR] Could not resolve "node:fs"
    node_modules/.bun/evlog@2.19.1+83d5fd7b249dbeef/node_modules/evlog/dist/pretty-error-snippet.node-itfCajBM.mjs:4:29:                   4 │ import { readFileSync } from "node:fs";
        ╵                              ~~~~~~~~~
  The package "node:fs" 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

Reproduction

  1. Set up a Convex project
  2. import { defineErrorCatalog } from 'evlog'; anywhere

Logs or structured output (optional)

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions