✦ Oplossingen · Server- en developerfouten

Error: ENOENT: no such file or directory in Node.js en npm

‘ENOENT: no such file or directory’ in Node.js of npm? Het pad bestaat niet vanuit waar je script draait. Zo vind je het juiste pad en los je het op.

Zo ziet de foutmelding eruit

  • Error: ENOENT: no such file or directory, open './config.json'
  • npm error enoent Could not read package.json: Error: ENOENT: no such file or directory, open '/home/gebruiker/package.json'
  • npm ERR! enoent ENOENT: no such file or directory, open '/home/gebruiker/package.json'
  • Error: spawn git ENOENT
  • code: 'ENOENT'

Waarom gebeurt dit?

ENOENT staat voor ‘Error NO ENTry’: het besturingssysteem vindt het bestand of de map op het opgegeven pad niet. In de melding staat welke handeling mislukte (open, stat, mkdir, scandir) en welk pad werd geprobeerd. Dat pad is je belangrijkste aanwijzing: kijk niet naar wat je dénkt dat er staat, maar naar wat Node.js echt probeerde te openen.

De meest voorkomende oorzaak is een relatief pad. Een pad als ./config.json wordt opgelost vanuit de huidige werkmap (process.cwd()): de map waaruit je het commando start. Dat is niet per se de map waar je script staat. Start je de app vanuit een andere map, via een procesmanager of een cronjob, dan wijst hetzelfde pad ineens naar een andere plek.

Andere oorzaken: een verschil in hoofdletters (Windows en macOS negeren dat standaard, Linux niet), een build-map zoals dist of build die op de server nooit is aangemaakt, een map die niet bestaat waarin je een bestand wilt schrijven, of npm dat je start in een map zonder package.json. Bij spawn … ENOENT gaat het om een programma dat niet gevonden wordt in het zoekpad (PATH).

Zo herken je dit probleem

  • De app werkt wel als je hem vanuit de projectmap start, maar niet vanuit een andere map, via PM2 of via cron.
  • Het werkt op je eigen Windows- of Mac-computer, maar niet op de Linux-server: denk aan hoofdletters in bestandsnamen.
  • Staat er Cannot find module met MODULE_NOT_FOUND, dan gaat het om een import of ontbrekend pakket; vaak helpt npm install.
  • Bestaat het bestand wel maar mag je het niet openen, dan krijg je EACCES: zie Permission denied.

Zo los je het op, stap voor stap

Menunamen kunnen per versie of toestel iets anders heten. Loop de stappen op volgorde af en stop zodra het werkt.

  1. Lees het volledige pad in de melding

    Kopieer het pad uit de foutmelding en controleer of het bestaat. Vaak zie je meteen dat het in de verkeerde map wordt gezocht, of dat een deel van de naam niet klopt. Controleer ook vanuit welke map je het commando startte.

    pwd
    ls -la /home/gebruiker/project/config.json
  2. npm: ga naar de map met package.json

    Could not read package.json betekent dat je npm start in een map zonder package.json. Na het klonen of uitpakken van een project zit dat bestand vaak een niveau dieper. Ga naar de juiste map en draai het commando opnieuw.

    ls
    cd mijn-project
    ls package.json
    npm install
  3. Gebruik paden vanaf de scriptmap

    Bouw paden naar bestanden die bij je code horen op vanaf de map van het script in plaats van de werkmap. In CommonJS gebruik je __dirname. In ES-modules bestaat __dirname niet; in recente Node.js-versies gebruik je import.meta.dirname, en anders leid je het pad af met fileURLToPath.

    // CommonJS
    const path = require('path');
    const config = path.join(__dirname, 'config.json');
    
    // ES-modules, recente Node.js-versies
    import path from 'node:path';
    const configPad = path.join(import.meta.dirname, 'config.json');
    
    // ES-modules, oudere Node.js-versies
    import { fileURLToPath } from 'node:url';
    const __dirname = path.dirname(fileURLToPath(import.meta.url));
    const configPad = path.join(__dirname, 'config.json');
  4. Controleer hoofdletters in bestandsnamen

    Op Linux zijn Logo.png en logo.png twee verschillende bestanden. Op je eigen computer valt dat vaak niet op. Zorg dat de naam in de code exact overeenkomt met de naam op schijf. Wijzig je in Git alleen de hoofdletters van een bestandsnaam, gebruik dan git mv, anders ziet Git de wijziging op Windows en macOS mogelijk niet.

    ls -la src/assets/ | grep -i logo
    git mv src/assets/Logo.png src/assets/logo.png
  5. Bouw de ontbrekende build-map

    Verwijst je startcommando naar dist/server.js of serveert de app een map build, dan moet die eerst worden gemaakt. Zulke mappen staan meestal in .gitignore en komen dus niet mee met een git pull. Draai de build op de server of laat je deploy-stap dat doen.

    npm ci
    npm run build
    ls dist/
  6. Maak de map aan voordat je schrijft

    Wil je een bestand schrijven in een map die nog niet bestaat, dan geeft Node.js ook ENOENT. Maak de map eerst aan met recursive: true; dat geeft geen fout als hij al bestaat.

    const fs = require('fs');
    fs.mkdirSync(path.join(__dirname, 'logs'), { recursive: true });
    fs.writeFileSync(path.join(__dirname, 'logs', 'app.log'), 'start\n');
  7. spawn ENOENT: zoek het programma

    Bij Error: spawn git ENOENT (of een ander programma) kan Node.js dat programma niet vinden. Controleer of het geïnstalleerd is en in het PATH staat van de gebruiker en omgeving waarin de app draait. Een dienst of cronjob heeft vaak een korter PATH dan je eigen terminal; geef dan het volledige pad op.

    which git
    echo $PATH
  8. Beheerder: zet de werkmap vast bij PM2 of systemd

    Draai je de app als dienst, geef dan expliciet de werkmap op. Zo zijn relatieve paden voorspelbaar, ook na een herstart van de server.

    # PM2
    pm2 start dist/server.js --name mijn-app --cwd /var/www/mijn-app
    
    # systemd (in de [Service]-sectie)
    WorkingDirectory=/var/www/mijn-app

Let op: Los ENOENT niet op door overal absolute paden van je eigen computer in de code te zetten. Dat werkt op de server niet. Bouw paden op vanaf de scriptmap of lees ze uit een instelling.

process.cwd() of __dirname?

Het verschil tussen deze twee verklaart de meeste ENOENT-fouten:

  • process.cwd(): de map waaruit het proces is gestart. Relatieve paden in fs-functies gaan hiervan uit.
  • __dirname (of import.meta.dirname in ES-modules): de map waarin het huidige scriptbestand staat. Dit verandert niet, hoe je de app ook start.
  • Gebruik __dirname voor bestanden die bij je code horen, en process.cwd() alleen voor bestanden die de gebruiker opgeeft vanaf de opdrachtregel.

Wanneer schakel je hulp in?

  • De app werkt lokaal wel, maar na de deploy op de server niet, en je vindt het verschil niet.
  • Je weet niet welke build-stappen of mappen op de server nodig zijn.
  • De app draait onder PM2, systemd of Docker en het pad of PATH is daar anders dan in je terminal.
  • Er ontbreken bestanden die er eerst wel waren en je weet niet of ze zijn verwijderd of nooit zijn geüpload.

Lukt het niet? Wij helpen

Kom je er met deze stappen niet uit, of wil je het liever niet zelf doen? We kijken online mee of komen langs. Hulp op afstand kost €20 per uur; komen we langs, dan is de prijs op aanvraag. Je weet vooraf waar je aan toe bent.

Aanvraag

Hulp aanvragen

Schrijf kort wat er misgaat en wat je al hebt geprobeerd. Kies of we bellen, online meekijken of langskomen.

Veelgestelde vragen

Vragen over dit probleem

Wat betekent ENOENT?

Het bestand of de map op het opgegeven pad bestaat niet. Kijk naar het pad in de melding en controleer vanuit welke map je de app start.

Waarom krijg ik ‘Could not read package.json’?

Je draait npm in een map zonder package.json. Ga met cd naar de projectmap waarin dat bestand staat.

Waarom werkt het op Windows wel en op de server niet?

Vaak door hoofdletters: Windows ziet Foto.jpg en foto.jpg als hetzelfde bestand, Linux niet. Een andere werkmap of ontbrekende build-map kan ook de oorzaak zijn.

Wat is het verschil tussen ENOENT en Cannot find module?

ENOENT gaat over een bestand dat je code zelf opent. Cannot find module gaat over een import of require die Node.js niet kan vinden, vaak een ontbrekend pakket.