Skip to content

[BUG] When executing opennextjs-cloudflare build within a development container on Docker Desktop for Mac, the generated open-next.config.mjs file has incorrect permissions, causing the build to fail. #930

@Suntory-Y-Water

Description

@Suntory-Y-Water

Describe the bug

Overview of the Issue

When executing opennextjs-cloudflare build within a development container on Docker Desktop for Mac, the permissions of the generated open-next.config.mjs file become abnormal, causing esbuild to fail to read the file and the build to fail. Conversely, executing the same command on the host OS (macOS) completes the build successfully.

Error Details

✘ [ERROR] Could not resolve "./open-next.config.mjs"

    .open-next/server-functions/default/index.mjs:1949:30:
      1949 │   const config = await import("./open-next.config.mjs").then((m) => m.default);
           ╵                               ~~~~~~~~~~~~~~~~~~~~~~~~

Error: Build failed with 1 error:
.open-next/server-functions/default/index.mjs:1949:30: ERROR: Could not resolve "./open-next.config.mjs"

Environment Information

Host OS Environment

  • macOS (using Docker Desktop)

Development Container Environment

  • VSCode Dev Container
  • Mounted Filesystem Type: fakeowner
  • User: node (uid=1000, gid=1000)

Package Versions

{
  "@opennextjs/cloudflare": "^1.9.1",
  "next": "15.5.0",
  "wrangler": "^4.38.0"
}

Development Container Base Images (Tried both)

  • mcr.microsoft.com/devcontainers/javascript-node:22-bookworm
  • node:22-bookworm

Abnormal Permissions on Generated Files

The permission for configuration files generated in the .open-next/.build/ directory is set to 0200 (write-only).

$ ls -la .open-next/.build/
total 44
drwxr-xr-x  7 node node   224 Oct  4 06:31 .
drwxr-xr-x 11 node node   352 Oct  4 06:31 ..
-rw-r--r--  1 node node 17288 Oct  4 06:31 cache.cjs
-rw-r--r--  1 node node  6243 Oct  4 06:31 composable-cache.cjs
drwxr-xr-x  5 node node   160 Oct  4 06:31 durable-objects
--w-------  1 node node  6756 Oct  4 06:31 open-next.config.edge.mjs
--w-------  1 node node  6978 Oct  4 06:31 open-next.config.mjs

Detailed information from the stat command:

$ stat .open-next/.build/open-next.config.mjs
  File: .open-next/.build/open-next.config.mjs
  Size: 6978      	Blocks: 16         IO Block: 4096   regular file
Device: 0,42	Inode: 226871      Links: 1
Access: (0200/--w-------)  Uid: ( 1000/    node)   Gid: ( 1000/    node)

Normally, files generated during the build process should have readable permissions like 0644 (-rw-r--r--), but here they are in an abnormal state of 0200 (--w-------, writeable only by the owner).

Complete Corruption of Copied Files

What is more problematic is that the permission of open-next.config.mjs copied to .open-next/server-functions/default/ is completely corrupted.

$ ls -la .open-next/server-functions/default/
-?????????  ? ?    ?        ?            ? open-next.config.mjs
ls: cannot access '.open-next/server-functions/default/open-next.config.mjs': Permission denied

The display -????????? indicates a state where permission information cannot be retrieved at the file system level. Consequently, when esbuild attempts to import this file, access is denied at the file system level.

Verification on the Host OS

When building the same project directly on the host OS (macOS), all files are generated with correct permissions (-rw-r--r--), and the build succeeds. This confirmed that the issue is specific to the container environment.

Verification by Changing the Base Image

We verified this by changing the base image for the development container in the following sequence, but the same error occurred in all cases:

  1. mcr.microsoft.com/devcontainers/javascript-node:22-bookworm (Original setting) $\rightarrow$ Error occurred
  2. node:22-bookworm (Changed to the official image) $\rightarrow$ The same error occurred

From these results, it is considered to be a file system level issue, independent of the type of Node image.

User Permission Check

The user permissions inside the development container are set correctly, and there are no issues such as UID/GID mismatches.

$ id
uid=1000(node) gid=1000(node) groups=1000(node),102(docker),998(nvm),999(npm)

The file ownership is also 1000:1000, confirming that the issue is not related to user permissions.

It builds successfully on the host OS.

Configuration File

The configuration file for the project where the issue occurs is as follows:

open-next.config.ts

import { defineCloudflareConfig } from '@opennextjs/cloudflare';

export default defineCloudflareConfig();

next.config.ts

import type { NextConfig } from 'next';
import { initOpenNextCloudflareForDev } from '@opennextjs/cloudflare';

const nextConfig: NextConfig = {
  /* config options here */
};

export default nextConfig;

initOpenNextCloudflareForDev();

wrangler.jsonc

{
  "main": "./custom-worker.ts",
  "compatibility_flags": ["nodejs_compat", "global_fetch_strictly_public"],
  "assets": {
    "directory": ".open-next/assets",
    "binding": "ASSETS"
  }
}

Steps to reproduce

Reproduction Steps

  1. Open the project using VSCode Dev Container in an environment where Docker Desktop for Mac is installed.
  2. Run pnpm install inside the development container to install dependencies.
  3. Run pnpm run schedule (which internally executes opennextjs-cloudflare build).
  4. The build fails with the error mentioned above.

When running the same command directly on the host OS (macOS), the build succeeds.

repo: https://github.com/Suntory-Y-Water/cc-vault

Expected behavior

The "opennextjs-cloudflare build" command completes the build successfully.

@opennextjs/cloudflare version

1.9.1

Wrangler version

4.41.0

next info output

$ pnpm dlx next info
Using vars defined in .dev.vars

Operating System:
  Platform: linux
  Arch: arm64
  Version: #1 SMP Wed Sep  3 15:35:15 UTC 2025
  Available memory (MB): 7838
  Available CPU cores: 12
Binaries:
  Node: 22.19.0
  npm: 10.9.3
  Yarn: 1.22.22
  pnpm: 10.0.0
Relevant Packages:
  next: 15.5.4 // Latest available version is detected (15.5.4).
  eslint-config-next: N/A
  react: 19.2.0
  react-dom: 19.2.0
  typescript: N/A
Next.js Config:
  output: N/A

Additional context

logging

node ➜ /workspaces/cc-vault (fix-relase-please-auto-merge) $ pnpm run build:cf

> [email protected] build:cf /workspaces/cc-vault
> opennextjs-cloudflare build


┌─────────────────────────────┐
│ OpenNext — Cloudflare build │
└─────────────────────────────┘

App directory: /workspaces/cc-vault
Next.js version : 15.5.0
@opennextjs/cloudflare version: 1.9.1
@opennextjs/aws version: 3.8.0

┌─────────────────────────────────┐
│ OpenNext — Building Next.js app │
└─────────────────────────────────┘


> [email protected] build /workspaces/cc-vault
> next build

Attention: Next.js now collects completely anonymous telemetry regarding usage.
This information is used to shape Next.js' roadmap and prioritize features.
You can learn more, including how to opt-out if you'd not like to participate in this anonymous program, by visiting the following URL:
https://nextjs.org/telemetry

Using vars defined in .dev.vars
   ▲ Next.js 15.5.0
   - Environments: .env

   Creating an optimized production build ...
Using vars defined in .dev.vars
Using vars defined in .dev.vars
Using vars defined in .dev.vars
 ✓ Compiled successfully in 5.0s
 ✓ Linting and checking validity of types    
 ✓ Collecting page data    
Using vars defined in .dev.vars
 ✓ Generating static pages (13/13)
 ✓ Collecting build traces    
 ✓ Finalizing page optimization    

Route (app)                                 Size  First Load JS    
┌ ƒ /                                      849 B         120 kB
├ ƒ /_not-found                            140 B         101 kB
├ ƒ /features                              162 B         105 kB
├ ƒ /help                                  140 B         101 kB
├ ƒ /privacy                               140 B         101 kB
├ ○ /robots.txt                            140 B         101 kB
├ ƒ /search                                849 B         120 kB
├ ƒ /sitemap.xml                           140 B         101 kB
├ ƒ /terms                                 140 B         101 kB
└ ƒ /weekly-report                         161 B         105 kB
+ First Load JS shared by all             101 kB
  ├ chunks/829-4ca80ae76df7907c.js       45.2 kB
  ├ chunks/c8c9667b-a0369b4d9c8bb3df.js  54.2 kB
  └ other shared chunks (total)          1.93 kB


○  (Static)   prerendered as static content
ƒ  (Dynamic)  server-rendered on demand


┌──────────────────────────────┐
│ OpenNext — Generating bundle │
└──────────────────────────────┘

Bundling middleware function...
Bundling static assets...
Bundling cache assets...
Building server function: default...
Applying code patches: 2.361s
# copyPackageTemplateFiles
⚙️ Bundling the OpenNext server...

✘ [ERROR] Could not resolve "./open-next.config.mjs"

    .open-next/server-functions/default/index.mjs:1949:30:
      1949 │   const config = await import("./open-next.config.mjs").then((m) => m.default);
           ╵                               ~~~~~~~~~~~~~~~~~~~~~~~~

opennextjs-cloudflare build

Build an OpenNext Cloudflare worker

Options:
      --help                        Show help                          [boolean]
      --version                     Show version number                [boolean]
  -c, --config                      Path to Wrangler configuration file [string]
      --configPath                  Path to Wrangler configuration file
                                                           [deprecated] [string]
  -e, --env                         Wrangler environment to use for operations
                                                                        [string]
  -s, --skipNextBuild, --skipBuild  Skip building the Next.js app
                                                      [boolean] [default: false]
      --noMinify                    Disable worker minification
                                                      [boolean] [default: false]
      --skipWranglerConfigCheck     Skip checking for a Wrangler config
                                                      [boolean] [default: false]
      --openNextConfigPath          Path to the OpenNext configuration file
                                                                        [string]

Error: Build failed with 1 error:
.open-next/server-functions/default/index.mjs:1949:30: ERROR: Could not resolve "./open-next.config.mjs"
    at failureErrorWithLog (/workspaces/cc-vault/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:1467:15)
    at /workspaces/cc-vault/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:926:25
    at runOnEndCallbacks (/workspaces/cc-vault/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:1307:45)
    at buildResponseToResult (/workspaces/cc-vault/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:924:7)
    at /workspaces/cc-vault/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:951:16
    at responseCallbacks.<computed> (/workspaces/cc-vault/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:603:9)
    at handleIncomingPacket (/workspaces/cc-vault/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:658:12)
    at Socket.readFromStdout (/workspaces/cc-vault/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:581:7)
    at Socket.emit (node:events:519:28)
    at Socket.emit (node:domain:489:12) {
  errors: [Getter/Setter],
  warnings: [Getter/Setter]
}
 ELIFECYCLE  Command failed with exit code 1.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingtriage

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions