netlify / netlify/cli

`netlify dev` with `--cwd` from outside the project: every function 500s with "module is not defined in ES module scope" (`detectZisiBuilder` passes a string to `readPackageUp`)

Open Beginner friendly
#8,423 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
1.9k
Forks
474
Avg merge
23h 30m
Merged PRs (30d)
53

Description

Describe the bug

detectZisiBuilder determines whether the project's package.json has "type": "module" like this:

https://github.com/netlify/cli/blob/85c0113195d65409856e0359533ff0756313b903/src/lib/functions/runtimes/js/builders/zisi.ts#L189-L191

// @ts-expect-error(serhalp) -- We seem to be incorrectly using this function, but it seems to work... Investigate.
const packageJson = await readPackageUp(func.mainFile)
const hasTypeModule = packageJson?.packageJson.type === 'module'

read-package-up expects an options object ({ cwd }), not a file path string. The string is silently ignored (find-up reads options.cwd, which is undefined), so the lookup always starts from process.cwd() instead of the function's directory. The @ts-expect-error TODO on that line is exactly this bug — it only "seems to work" because process.cwd() is usually inside the project.

It stops working when netlify dev is run with --cwd <project> from a directory outside the project: the CLI honors --cwd for config resolution but never calls process.chdir(), so readPackageUp searches upward from the invocation directory. If no package.json exists there or in its ancestors, hasTypeModule is false, and buildFunction skips writing the {"type":"commonjs"} marker into each function's .netlify/functions-serve/<name>/ directory:

https://github.com/netlify/cli/blob/85c0113195d65409856e0359533ff0756313b903/src/lib/functions/runtimes/js/builders/zisi.ts#L91-L100

In a project whose root package.json has "type": "module", Node then parses every zisi/esbuild CJS function bundle as ESM, and every function invocation 500s with:

ReferenceError: module is not defined in ES module scope

Running the identical command from inside the project works (the buggy fallback happens to resolve the right package.json), which is presumably why this is rarely reported. Editors/wrappers that spawn netlify dev --cwd <project> with a different working directory hit it every time.

A secondary effect of the same line: mustUseEsbuild = hasTypeModule || mustTranspile is also computed from the wrong package.json, so a "type": "module" project with plain .js functions and no explicit node_bundler wouldn't get esbuild auto-selected either.

Suggested fix
const packageJson = await readPackageUp({ cwd: path.dirname(func.mainFile) })

This is exactly what @netlify/functions-dev already does in its equivalent code path (its dist/main.js: readPackageUp({ cwd: path.dirname(func.mainFile) })), and it lets you drop the @ts-expect-error. Happy to open a PR.

Steps to reproduce

  1. Create a project with:
    • root package.json containing "type": "module"
    • netlify.toml with [functions] node_bundler = "esbuild" and a v1 TypeScript function (e.g. netlify/functions/hello.ts)
  2. From a directory outside the project that has no package.json in itself or any ancestor (e.g. C:\ or a fresh temp dir), run:
    netlify dev --cwd /path/to/project
    
  3. curl http://localhost:8888/.netlify/functions/hello500, terminal shows ReferenceError: module is not defined in ES module scope, and .netlify/functions-serve/hello/ contains no package.json marker.
  4. Run the same netlify dev from inside the project directory → the function works and the {"type":"commonjs"} marker is written.

Verified on netlify-cli 26.0.1; the code is unchanged in v27.1.1 and current main (85c0113). Patching the installed dist/lib/functions/runtimes/js/builders/zisi.js with the one-line fix above resolves it.

Configuration

[build]
  publish = "dist"

[functions]
  node_bundler = "esbuild"

Environment

  System:
    OS: Windows 11 10.0.26200
    CPU: (8) x64 Intel(R) Core(TM) Ultra 7 258V
    Memory: 8.57 GB / 31.49 GB
  Binaries:
    Node: 24.15.0 - C:\Program Files\nodejs\node.EXE
    npm: 11.12.1 - C:\Program Files\nodejs\npm.CMD
  npmGlobalPackages:
    netlify-cli: 26.0.1

(Reproduced on 26.0.1; bug confirmed present in 27.1.1 and main by source inspection. Not OS-specific — the lookup falls back to process.cwd() on any platform.)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in src/lib/functions/runtimes/js/builders/zisi.ts at detectZisiBuilder and buildFunction, then inspect how readPackageUp is called and how the function package marker is written. Reproduce with netlify dev --cwd /path/to/project from outside the project, and confirm that functions no longer return the module-scope error and the expected marker is created.

Written by the indexing model from the issue text.

Assessment

Tech stack
node.js, typescript
Domain
cli
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.