Skip to content

nextjs_standalone_build npm deps not exec-configured, breaking cross-platform image builds with js_image_layer on macOS #2814

@miraziz-taifin

Description

@miraziz-taifin

Rules version: 3.0.3
Bazel version: 9.1.0 (Bzlmod)
Platform: macOS (darwin/amd64) building a linux/amd64 OCI image
Note: This report was generated by an LLM; I don't fully understand the breakage but the result is a pain point in our dev flow


Problem

When js_image_layer is applied to a nextjs_standalone_server target with a linux platform transition, the transition cascades transitively to nextjs_standalone_build. The next build action runs on the macOS exec platform but its npm inputs — including @next/swc-* — are now selected for the linux target platform. The linux SWC binary cannot execute on macOS, so Next.js attempts a live download via pnpm config get registry, which fails because pnpm is not in the sandboxed action PATH.

Reproduction

MODULE.bazel

bazel_dep(name = "rules_oci", version = "2.3.0")
  oci = use_extension("@rules_oci//oci:extensions.bzl", "oci")                                                                                                                                                     
  oci.pull(name = "node24_slim", image = "docker.io/library/node",                                                                                                                                                 
           digest = "sha256:...", platforms = ["linux/amd64"])                                                                                                                                                     
  use_repo(oci, "node24_slim", "node24_slim_linux_amd64")

BUILD.bazel

  nextjs_standalone_build(name = "standalone", ...)                                                                                                                                                                
  nextjs_standalone_server(name = "server", app = ":standalone", ...)
                                                                                                                                                                                                                   
  js_image_layer(                                                                                                                                                                                                  
      name = "server_layers",                                                                                                                                                                                      
      binary = ":server",                                                                                                                                                                                          
      root = "/app",                                        
      platform = ":linux_amd64",   # triggers the cascading transition                                                                                                                                             
  )                                                                                                                                                                                                                
                                                                                                                                                                                                                   
  bazel build //apps/web:server_layers                                                                                                                                                                             
  # Error: /bin/sh: pnpm: command not found                 
  # (next build tried to download the darwin SWC binary because linux SWC can't execute)                                                                                                                           

Root cause

nextjs_standalone_build feeds npm packages to next build as target-configured deps. When a downstream platform transition flips the target platform to linux, those deps resolve to linux npm packages. Because next build is a Bazel action that executes on the exec platform (macOS), it requires exec-platform npm packages — particularly the SWC native binary. The action and its tool requirements are split across configurations.

Expected behaviour

js_image_layer on macOS targeting linux/amd64 should produce a valid linux image. The next build action should always use exec-platform npm packages (specifically SWC) regardless of the downstream target platform, while the packaged runfiles in the image layers use target-platform packages.

Suggested fix

In nextjs_standalone_build (or the underlying js_run_binary/action), mark the npm dep attributes that provide build-time tooling (SWC, webpack, etc.) with cfg = "exec" so they always resolve to the host platform. The build output (.next/, server.js) is platform-neutral JS and can flow through downstream target transitions unchanged.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinghelp wantedAspect isn't prioritizing this, but the community could

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions