Error: Cannot find module @rollup/rollup-linux-x64-gnu znamená, že se na tvém stroji nikdy nenainstaloval nativní binární soubor Rollupu pro tvou platformu. Rollup 4 dodává svůj parser jako samostatný zkompilovaný balíček pro každou platformu, npm nainstaluje jen ten, který odpovídá, a správnému balíčku spolehlivě zabrání v příchodu tři věci: soubor package-lock.json vytvořený na jiném operačním systému verzí npm se známou chybou v optional dependencies, složka node_modules zkopírovaná z jiného stroje (velmi často do Docker image), nebo instalace spuštěná s vypnutými optional dependencies. Oprava, která funguje téměř vždy, je ta, kterou vypisuje sám Rollup: smaž node_modules i package-lock.json, znovu spusť npm install a commitni nový lockfile. Zbytek článku je o tom, jak to udělat, aniž bys rozbil cokoli dalšího, a jak zařídit, aby se to nevrátilo při příštím deployi.
Co ta chyba vlastně říká#
Celá zpráva pochází z loaderu samotného Rollupu a je nezvykle upřímná:
Error: Cannot find module @rollup/rollup-linux-x64-gnu. npm has a bug relatedto optional dependencies (https://github.com/npm/cli/issues/4828). Please try`npm i` again after removing both package-lock.json and node_modules directory.Nejdůležitější je název balíčku na začátku. Říká ti, na jaké platformě si Rollup myslí, že běží, a tedy jaký binární soubor šel hledat. Název skládá ze tří údajů: operačního systému, architektury procesoru a na Linuxu také knihovny C.
| Přípona balíčku | Kde ji uvidíš |
|---|---|
linux-x64-gnu | Běžné linuxové servery, image Debianu a Ubuntu, většina CI runnerů |
linux-x64-musl | Alpine Linux včetně image node:*-alpine |
linux-arm64-gnu | Servery s ARM, Docker na Apple Silicon, 64bitový Raspberry Pi |
linux-arm64-musl | Alpine na ARM |
darwin-arm64 / darwin-x64 | macOS na Apple Silicon / Intelu |
win32-x64-msvc | Windows na x64 |
win32-arm64-msvc | Windows na ARM |
Existují i další - FreeBSD, RISC-V, s390x, 32bitové ARM a jiné - ale tabulka pokrývá téměř každé hlášení, na které narazíš. Samotná přípona je diagnóza. Pokud je tvůj server běžný linuxový stroj s x64 a chyba jmenuje linux-x64-musl, běžíš uvnitř Alpine, ať jsi to tak chtěl, nebo ne. Pokud jsi na Windows a chyba jmenuje win32-x64-msvc, hraje v tom roli cizí lockfile.
Na Linuxu se Rollup mezi gnu a musl rozhoduje za běhu tak, že se zeptá Node na jeho process report: pokud report obsahuje verzi glibc, je to gnu, jinak musl. Nic z toho nenastavuješ a nejde to přebít proměnnou prostředí.
Proč Rollup potřebuje binárku a proč ho přináší Vite#
Rollup 3 byl čistý JavaScript. Rollup 4, vydaný v říjnu 2023, nahradil svůj JavaScriptový parser parserem ze SWC, zkompilovaným z Rustu do nativního doplňku pro Node. Parsování se tím výrazně zrychlilo, ale vznikl problém, který mají všechny nativní balíčky: jeden zkompilovaný soubor nemůže běžet na všech platformách.
Rollup používá postup, který sdílí esbuild, SWC, Lightning CSS, @tailwindcss/oxide z Tailwind CSS 4 a balíčky @img/* ze sharp: publikuje jeden drobný balíček pro každou platformu a všechny je vyjmenuje v optionalDependencies hlavního balíčku. Každý platformní balíček si ve vlastním package.json deklaruje, jaký operační systém a procesor podporuje (a u linuxových buildů také jakou knihovnu C):
{ "name": "@rollup/rollup-linux-x64-gnu", "os": ["linux"], "cpu": ["x64"], "libc": ["glibc"], "main": "./rollup.linux-x64-gnu.node"}Když npm instaluje rollup, vidí dvacet a něco optional dependencies, porovná os a cpu každé z nich s aktuálním strojem, ty nevyhovující tiše přeskočí a nainstaluje tu, která sedí. Optional znamená, že selhání nebo neshoda není chyba. Právě to umožňuje, aby to fungovalo napříč platformami, a právě proto to při problému selže potichu: npm ti nikdy neřekne, že přeskočil ten jediný balíček, který jsi potřeboval.
Většina lidí Rollup nikdy neinstaluje schválně. Přichází s Vite. Vite 5, 6 i 7 závisí na Rollupu 4 při produkčních buildech, takže chyba se objeví při vite build, obvykle v CI jobu nebo na serveru, málokdy na notebooku, kde se projekt zakládal. Přechod z Vite 4 na Vite 5 byl pro spoustu projektů okamžik, kdy se s tím setkaly poprvé, protože Vite 4 ještě používal Rollup 3 a vlastní platformní binárky kromě esbuildu neměl.
Vite 8 nahrazuje Rollup nástrojem Rolldown, který používá stejný mechanismus pod jinými názvy: @rolldown/binding-linux-x64-gnu a další. Pokud jsi na Vite 8 a vidíš chybu o chybějícím nativním bindingu z Rolldownu, platí pro tebe všechno z tohoto článku - mění se jen názvy balíčků.
Chyba npm za většinou případů#
Issue, na které Rollup odkazuje, npm/cli#4828, bylo otevřeno v dubnu 2022 a popisuje tohle: když npm znovu generuje package-lock.json ve chvíli, kdy už existuje složka node_modules, sestaví lockfile z toho, co je nainstalováno, a ne z úplných metadat závislostí. Na Macu to znamená, že lockfile skončí s položkou @rollup/rollup-darwin-arm64 a bez všech ostatních platformních balíčků, protože se tam nikdy neinstalovaly.
Takový lockfile se pak commitne. Na Linuxu npm ci nainstaluje přesně to, co lockfile uvádí - což linuxovou binárku neobsahuje - a skončí bez jediného varování. První známka potíží přijde až při buildu.
Spouštěč je obvykle nevinný: někdo smaže jen lockfile, aby vyřešil merge konflikt nebo varování o peer dependency, spustí npm install s ponechanou složkou node_modules a výsledek commitne. Stává se to i na Windows, a tak lockfile vygenerované na Linuxu rozbíjí build Windows vývojářům v opačném směru, s chybou win32-x64-msvc.
Se stavem opravy je to složité. Podle komentářů v issue už poslední vydání npm 11 nevyhazují ostatní platformy u balíčků, které je všechny deklarují jako optional dependencies, což je případ Rollupu, jiné komentáře ale popisují, že se problém vrací v pozdějších vydáních 11.x. Neplánuj podle toho, že to nějaká konkrétní verze npm spraví. Plánuj podle lockfilu, který jsi zkontroloval.
Než cokoli změníš, potvrď příčinu#
Dva příkazy ti řeknou, kterou ze tří příčin máš. Nejdřív na stroji, kde to padá, zeptej se npm, jestli je binárka nainstalovaná:
$ npm ls @rollup/rollup-linux-x64-gnumy-app@1.0.0 /srv/app└── (empty)Prázdný výsledek znamená, že ji npm nenainstaloval nikde ve stromu závislostí. Potom se podívej do samotného lockfilu a spočítej platformní položky:
$ grep -c '"node_modules/@rollup/rollup-' package-lock.json1Zdravý lockfile uvádí všechny platformy, které Rollup publikuje, takže počet je kolem dvaceti podle verze Rollupu. Počet jedna nebo dva je chyba npm: lockfile vznikl na jednom stroji a zná jen jeho binárku. Chceš-li zjistit, kterou zná:
$ grep '"node_modules/@rollup/rollup-' package-lock.json "node_modules/@rollup/rollup-darwin-arm64": {Pokud je lockfile úplný a balíček přesto chybí, problém není v lockfilu. Podívej se, jak se node_modules na stroj dostalo a jestli nejsou vypnuté optional dependencies - obojí rozebírají další sekce.
Oprava: správně přegeneruj lockfile#
Na stroji, kde obvykle měníš závislosti:
$ rm -rf node_modules package-lock.json$ npm install$ grep -c '"node_modules/@rollup/rollup-' package-lock.json$ git add package-lock.json$ git commit -m "fix: regenerate lockfile with all platform binaries"Ve Windows v PowerShellu je první řádek Remove-Item -Recurse -Force node_modules, package-lock.json. Důležité je smazat node_modules. Smazat jen lockfile a nechat node_modules na místě je přesně to, co chybu spouští.
Tahle oprava má cenu a je dobré si ji říct jasně. Bez lockfilu npm install znovu vyhodnotí každý rozsah verzí v package.json podle toho, co je dnes publikované. Verze ^5.4.0, která byla zafixovaná na 5.4.2, se může vrátit jako 5.4.19. U většiny projektů je to neškodné, ale není to nic: prohlédni si diff lockfilu, spusť testy i build a nasaď to jako aktualizaci závislostí, ne jako jednořádkovou opravu. Pokud potřebuješ menší změnu, další sekce nabízí užší možnosti.
Na serveru se nemění nic, jen dostane správný lockfile. Používej tam dál npm ci - nainstaluje přesně to, co říká lockfile, což je teď správně. Článek npm ci vs npm install vysvětluje, proč by server nikdy neměl být strojem, který lockfile zapisuje. Pokud tě svádí přepnout server na npm install, aby chyba zmizela, nedělej to: se stávajícím rozbitým lockfilem často binárku stejně přeskočí, a když ne, je to proto, že na serveru přepsal tvůj strom závislostí.
Užší opravy, když nejde přegenerovat všechno#
Někdy se plné přegenerování nedá připustit - release větev, zmrazení kvůli auditu, monorepo, kde jeden lockfile pokrývá čtyřicet balíčků. Jsou dvě užší možnosti, obě s kompromisy.
Chybějící binárku deklaruj sám. Přidej platformní balíček do optionalDependencies ve vlastním package.json, přesně ve stejné verzi, jakou má rollup v tvém lockfilu:
{ "optionalDependencies": { "@rollup/rollup-linux-x64-gnu": "4.40.0" }}Pak spusť npm install, aby ho lockfile zaznamenal. Protože je optional, npm ho na Macu přeskočí a na Linuxu nainstaluje. Háček je ve verzi: binárka musí odpovídat vydání Rollupu, ke kterému patří, a až Vite příště natáhne novější Rollup, tvůj pin bude zastaralý. Ber to jako provizorium a odstraň to, jakmile lockfile správně přegeneruješ.
Použij WebAssembly build Rollupu. Rollup publikuje @rollup/wasm-node, tentýž bundler s parserem zkompilovaným do WebAssembly místo nativního kódu. Nemá žádné platformní balíčky, takže celá tahle třída chyb zmizí. Namiř na něj všechny kopie rollup ve stromu pomocí npm override:
{ "overrides": { "rollup": "npm:@rollup/wasm-node" }}Po přidání spusť npm install. Cenou je rychlost - parsování ve WebAssembly je znatelně pomalejší než nativní, což se projeví u velkých buildů a u malých sotva postřehneš. Je to rozumná volba pro platformy, pro které Rollup nativní build nemá, a pro týmy, které chtějí raději pomalejší build než křehký.
node_modules kopírované mezi stroji a Docker#
Druhá příčina s chybou npm nemá nic společného. Složka node_modules nainstalovaná na jedné platformě obsahuje binárku té platformy a nic jiného, takže po přenesení na jinou platformu zůstane nový stroj bez své binárky. Lockfile může být dokonalý a stejně se to stane.
Nejčastější způsoby, jak k tomu dojde:
- Nahrání složky projektu i s `node_modules` přes SFTP nebo jako zip. Složka nainstalovaná na Macu nese
darwin-arm64a nic pro Linux. - Commitování `node_modules` do Gitu. Patří do
.gitignore, vždy - je velká, závisí na platformě a z lockfilu se obnoví za pár sekund. - Docker `COPY . .` po `npm ci`. To je klasika. Image nainstaluje správnou linuxovou binárku a hned další řádek přes ni překopíruje
node_modulesz tvého notebooku.
Vzor Dockerfilu, který tomu předchází, nejdřív zkopíruje jen manifesty, nainstaluje uvnitř image a zdrojové kódy zkopíruje až potom:
FROM node:22-bookworm-slim AS buildWORKDIR /appCOPY package.json package-lock.json ./RUN npm ciCOPY . .RUN npm run buildTo samo o sobě nestačí, protože COPY . . stále zkopíruje lokální node_modules, pokud existuje. Zastaví to soubor .dockerignore vedle Dockerfilu:
node_modulesdist.gitBuildy se tím také zrychlí, protože Docker už neposílá stovky megabajtů build contextu, které stejně zahodí.
Vývojová prostředí s Docker Compose mají vlastní verzi téhle potíže. Bind mount typu .:/app nahradí /app v image složkou tvého projektu, včetně node_modules z notebooku. Obvyklá oprava je anonymní volume pro tuto složku, které zachová vlastní kopii kontejneru:
services: web: build: . volumes: - .:/app - /app/node_modulesŠirší postupy najdeš v článcích Docker na VDS a Docker Compose pro malé stacky.
Alpine, musl a ARM#
Image založené na Alpine používají místo glibc knihovnu musl, takže Rollup požaduje linux-x64-musl. S úplným lockfilem a instalací, která běží uvnitř image Alpine, to prostě funguje: npm vybere build pro musl. Rozbije se to, když instalace proběhla jinde - node_modules vytvořené na Debianu nebo na CI runneru a zkopírované do stage s Alpine obsahuje linux-x64-gnu a Rollup uvnitř Alpine ho nenačte. Pravidlo je stejné jako v každém jiném případě: spouštěj npm ci ve stejném image, nebo aspoň na stejném základu, ve kterém poběží build.
Pokud nemáš silný důvod používat Alpine, image založený na Debianu, například node:22-bookworm-slim, odstraní celou kategorii překvapení s nativními moduly za cenu o něco většího image.
K ARM se lidé dostanou přes Apple Silicon. Docker na Macu s řadou M staví ve výchozím stavu image linux/arm64, takže instalace při buildu stáhne linux-arm64-gnu. Takový image na serveru s x64 nepoběží z mnoha důvodů nad rámec Rollupu. Cíl proto zadej při buildu výslovně:
$ docker build --platform linux/amd64 -t my-app .Podobně vypadá související selhání, které ale není chybou npm. Pokud stack trace zmiňuje něco jako GLIBC_2.xx not found, binárka je nainstalovaná, jenže knihovna C v systému je příliš stará na to, aby ji načetla - typicky u prastarého build image. Aktualizuj základní image, nereinstaluj.
Nevypínej optional dependencies#
Třetí příčina je způsobená vlastní rukou. npm ci --omit=optional, starší --no-optional, omit=optional v souboru .npmrc nebo NPM_CONFIG_OMIT=optional v prostředí CI - všechno to říká npm, aby přeskočilo všechny optional dependencies, včetně binárky Rollupu, která je optional jen v tom smyslu, že npm má vybrat jednu. Rollup pak selže přesně tak, jako by udeřila ta chyba.
Tato nastavení se obvykle objeví ze starého návodu na zmenšování image nebo z obejití rozbité instalace jiného balíčku. Zkontroluj, co npm skutečně používá:
$ npm config get omitMělo by to nevypsat nic, nebo dev, pokud záměrně přeskakuješ vývojové závislosti. Problém je optional ve výpisu. Pozor i na další past: Vite a Rollup jsou devDependencies, takže npm ci --omit=dev následované vite build také selže, ale s hláškou vite: not found, ne s touto chybou. Nainstaluj všechno, sestav a potom odstraň vývojové závislosti pomocí npm prune --omit=dev.
Na hostovaném aplikačním serveru#
Na hostingu postaveném na kontejnerech platí stejná pravidla a jediné skutečné rozhodnutí je, kde build běží. Na RE:NODE se plány pro aplikace v Node.js nasazují z GitHubu přes Git deploy v panelu, a když tvůj startovací příkaz spouští npm ci a build, běží na serveru - takže lockfile uvádějící všechny platformy Rollupu je celá oprava: commitni ho a nasaď znovu. Konzole v panelu zobrazuje výstup instalace a buildu nefiltrovaný, takže chybějící binárka se ukáže jako výše uvedená chyba, ne jako tichý pád - na co se v konzoli dívat, popisuje čtení konzole. Nenahrávej lokální node_modules přes správce souborů ani SFTP; nech ho postavit npm ci na serveru.
Pokud se server pořád restartuje, protože build uvnitř startovacího příkazu selhává, oprav lockfile, než ho restartuješ znovu. Hlídač počítá restarty po pádu: tři za hodinu vyvolají varování na stránce serveru a otevřou ticket, šest server pozastaví. Nasazení aplikace v Node z GitHubu provádí startovacím příkazem a sekvencí build a prune. Pokud se tvůj projekt s Vite sestaví do prostých statických souborů, Node za běhu vůbec nepotřebuješ - sestav ho v CI a servíruj složku dist, což popisuje hosting statických webů.
FAQ#
Proč build funguje na mém notebooku, ale na serveru ne?
Tvůj notebook má binárku pro vlastní platformu, nainstalovanou při prvním npm install. Server potřebuje jinou a buď ji lockfile neuvádí, nebo něco npm zabránilo ji nainstalovat. Kontrola grep -c výše ti řekne, který případ to je.
Spraví to smazání node_modules na serveru?
Ne, pokud je problém v lockfilu. npm ci stejně node_modules smaže a nainstaluje znovu z lockfilu, takže lockfile bez linuxové binárky dá pokaždé stejný výsledek. Lockfile je nutné přegenerovat a commitnout.
Mám @rollup/rollup-linux-x64-gnu nainstalovat jako běžnou závislost?
Ne. Běžná závislost není optional, takže instalace na každém Macu a Windows rovnou selže s chybou EBADPLATFORM. Pokud potřebuješ provizorium, dej ji do optionalDependencies přesně ve verzi Rollupu.
Vyhnu se tomu s pnpm nebo Yarnem?
Konkrétní chyba lockfilu je chyba npm, takže přechod na jiný správce balíčků ji často odstraní. Kopírování node_modules mezi platformami a vypnutí optional dependencies rozbijí všechny správce balíčků stejně, takže rady k Dockeru a .dockerignore platí dál.
Je za chybami platforem u esbuildu a SWC totéž?
Ano, mechanismus je stejný: jeden optional balíček na platformu. Zpráva esbuildu je jiná - říká, že jsi nainstaloval esbuild pro jinou platformu, než kterou používáš - ale opravy jsou stejné: úplný lockfile, instalace na cílové platformě a žádné kopírované node_modules.


