Deploy Error Decoder

ENOENT: no such file or directory — find the missing path

Quick answer: ENOENT (Error NO ENTry) means the file or directory at that path does not exist from where the process is running. Most often a relative path resolved against the wrong working directory, or a file that was not copied into the deploy or Docker image. Use absolute paths with path.join(__dirname, ...) and verify the file is actually present at runtime.

Not your exact error? Paste it into the Deploy Error Decoder →

What the error looks like

The message names the operation and the exact path that failed:

Error: ENOENT: no such file or directory, open '/app/config/app.json'
    at Object.openSync (node:fs:601:3)
  errno: -2, code: 'ENOENT', syscall: 'open', path: '/app/config/app.json'

# the same code with a relative path is the giveaway:
fs.readFileSync('./config/app.json')   // resolved against process.cwd()

Read the path field carefully. If it is an absolute path that should exist, the file is genuinely missing from the deploy. If it looks half-built or relative, the working directory or an empty variable is the problem.

Why it happens

Relative path, wrong working directory

A path like ./file resolves against process.cwd(), which differs in production from where you ran it locally.

File not copied into the image

.dockerignore excluded it, or a COPY step missed it, so it is absent at runtime.

Missing build artifact

The app expects a built file (dist/, .next/) that was never generated before running.

Case-sensitivity on Linux

Config.json works on macOS but fails on Linux, where the filesystem is case-sensitive.

Diagnose it in three steps

1

Print the resolved path and cwd

const path = require('path');
console.log('cwd:', process.cwd());
console.log('resolved:', path.resolve('./config/app.json'));
// Is the resolved path what you expect?
2

Check it exists at runtime

# on the server or in the container
ls -la /app/config/app.json
# inside the built image:
docker run --rm myimage ls -la /app/config
3

Confirm case and .dockerignore

git ls-files | grep -i app.json   # exact case?
cat .dockerignore                  # is the file excluded?
The real fix

Absolute paths, and make sure the file ships

For files bundled with your code, build the path from __dirname so it never depends on the working directory. For everything else, make sure the file is actually present at runtime - included in the image, built before start, and named with the exact case.

// BAD - depends on where the process was started
fs.readFileSync('./config/app.json');

// GOOD - absolute, relative to this source file
const path = require('path');
fs.readFileSync(path.join(__dirname, 'config', 'app.json'));

# make sure it ships in the image, then verify:
docker run --rm myimage ls -la /app/config

If it is a build artifact, run the build in your deploy pipeline before the app starts; if it is user data, create the directory (fs.mkdirSync(dir, { recursive: true })) before writing.

How Infraveil handles this

Verify the deploy before it serves

A missing file at runtime is a deploy-integrity problem - the artifact that ran is not the one you expected. On your own servers, Infraveil health-checks a service before it takes traffic and surfaces failures with their context, so a missing file or bad build is caught early, and recovery stays approval-gated and recorded.

Health checks confirm a service is actually working before traffic flows
Failures surface with context in one view, on servers you control
Recovery approval-gated and recorded

Frequently asked questions

What does ENOENT mean?

ENOENT stands for Error NO ENTry: the file or directory at the path your code used does not exist from the process's point of view. The message names the path and the failed operation (open, stat, scandir, unlink).

Why does it work locally but fail in production or Docker?

Usually the working directory differs, or the file was not copied into the image. A relative path resolves against process.cwd(), which is often different in production. Use an absolute path from __dirname and confirm the file is in the deployed artifact.

I can see the file - why ENOENT?

Common causes: a different working directory than you assume, case-sensitivity on Linux, a broken symlink, or a path built from an empty environment variable. Print the resolved absolute path and process.cwd() to see what was actually opened.

How do I prevent ENOENT?

Use path.join(__dirname, ...) for bundled files, make sure .dockerignore and COPY include what you need, build artifacts before running, create directories with recursive:true before writing, and match filename case exactly.