## TL;DR
The production webpack build bundles the entire Lab frontend, which needs far more heap than Node's default, so on small containers the build dies with an out-of-memory error. Set a larger Node heap with `NODE_OPTIONS=--max-old-space-size=4096` and re-run the build. If the machine itself is too small, build with `--minimize=False` to cut memory use, or build the extensions on a bigger machine and ship the built assets.

```text
jupyterlab build failed: webpack ran out of memory
```

## Use this when
- `jupyter lab build` dies with a JavaScript heap out-of-memory error or the process gets killed mid-build.
- The build succeeds on a developer laptop but OOMs in a small container or CI runner.
- Adding one more extension pushed a previously working build over the edge.

## Not for this skill when
- The build fails with a version conflict between a labextension and JupyterLab. That is a dependency conflict, a different fix.
- The build fails because an npm package cannot be fetched. That is a network or registry problem.

## Steps
1. Confirm it is really OOM: check the build log for 'heap out of memory' or check `dmesg` for the OOM killer naming the node process. Expected: evidence that memory, not code, killed the build.
2. Re-run with a bigger Node heap: `NODE_OPTIONS=--max-old-space-size=4096 jupyter lab build`. Expected: the build progresses past the point where it previously died.
3. If it still OOMs, disable minimization: `jupyter lab build --minimize=False`. Expected: lower peak memory at the cost of larger assets; the build completes.
4. Check how much RAM the machine actually has and what else is running. Expected: you know whether the box is simply too small (under ~4GB free for a full Lab build is tight).
5. If the machine is too small, build on a bigger machine or in CI with more RAM, then copy the built `static` assets or the whole environment. Expected: the small machine serves prebuilt assets without ever running webpack.
6. Pin the working recipe (heap size, minimize flag, machine size) in the image build docs so the next extension addition does not rediscover this. Expected: the build is reproducible from the documented recipe.

## Tool compatibility
JupyterLab 3.x and 4.x; Node.js 18.x and 20.x; webpack 5.x as bundled by Lab.

## Variant phrasings
### jupyter lab build javascript heap out of memory
The Node-side phrasing of the same OOM. Raise the heap with NODE_OPTIONS.

### webpack killed during jupyterlab build docker
The container phrasing. Either raise the heap or build the assets outside the small container.

### jupyter lab build runs out of memory ci
The CI phrasing. Give the build job more RAM or disable minimization.

## Why it happens
JupyterLab's production build runs the whole application through webpack with minimization, which holds the full module graph and minified output in memory at once. Node's default old-space heap (around 2GB on 64-bit) is simply smaller than what a Lab build with several extensions needs, and containers often add a hard memory ceiling on top. The failure looks like a build bug but it is a resource budget bug: the same sources build fine with a bigger heap. Disabling minimization trades asset size for a much smaller memory peak, which is why it rescues builds on machines that cannot take a bigger heap.

## Edge cases / pitfalls
- Setting the heap larger than the container's memory limit just moves the kill from Node's OOM to the container OOM killer. Size the heap below the container limit.
- `--minimize=False` ships larger JavaScript to every user. Fine for internal tools; think twice for public deployments.
- Each new extension grows the bundle. Revisit the heap budget whenever the extension set changes, not just once.
- Build caches can mask the OOM: a clean build (`jupyter lab clean` first) is the real test of the recipe.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_lwihrtVqkbo8mHrxPVeDYw
