Skip to content

workflow-node-module-error is too strict for shared modules #1817

@KentoMoriwaki

Description

@KentoMoriwaki

Summary

I ran into behavior from workflow-node-module-error that was different from what I expected after reading the docs, so I wanted to check whether this is:

  • expected behavior
  • a current limitation
  • or a bug / false positive

If this is working as intended, feel free to close this.

Reproduction

Minimal repro repo:

Versions:

  • workflow: 4.2.4
  • next: 16.1.6

Structure

The repro has this shape:

  • workflows/example.ts
    • "use workflow"
    • imports only isSupportedValue() from lib/shared.ts
  • workflows/steps.ts
    • "use step"
    • imports readFixtureFile() from lib/shared.ts
  • lib/shared.ts
    • exports isSupportedValue() (workflow-safe)
    • exports readFixtureFile() (uses node:path and node:fs/promises)

So a shared local module contains both:

  • a workflow-safe export
  • a step-only export that uses Node.js builtins

Steps to reproduce

git clone https://github.com/KentoMoriwaki/workflow-node-module-repro.git
cd workflow-node-module-repro
pnpm install
pnpm build

What I expected

From the docs, I expected this to work because:

  • the workflow only uses the workflow-safe export
  • the Node.js code is only used from the "use step" path

More specifically, I expected workflow/step code to be separated first, with dead code elimination happening before this check, so that step-only Node.js code in a shared module would not be flagged from the workflow side.

What actually happens

pnpm build fails with:

✘ [ERROR] You are attempting to use "node:fs/promises" which is a Node.js module. Node.js modules are not available in workflow functions.

    lib/shared.ts:7:9:
      7 │   return readFile(path.join(process.cwd(), "fixture.txt"), "utf8");
        │          ~~~~~~~~

✘ [ERROR] You are attempting to use "node:path" which is a Node.js module. Node.js modules are not available in workflow functions.

    lib/shared.ts:7:18:
      7 │   return readFile(path.join(process.cwd(), "fixture.txt"), "utf8");
        │                   ~~~~

Why I opened this

This might be expected, but it was surprising to me based on how I understood the docs around "use workflow" and "use step" boundaries.

If this is the intended constraint, a note in the docs about shared local modules would probably help, for example making it explicit that:

  • any module imported from workflow code must itself avoid top-level Node.js imports
  • even if those imports are only used by step-only exports in the same file

If I misunderstood the intended model here, please feel free to close this.

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