ErrLookupBackground articles › "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it

"open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it

File open errors — logged as open() "/path" failed, failed to open file, cannot create reader, or could not open file — mean the OS refused to open a file: it doesn't exist, the process lacks permission, the path is a directory, a symlink is broken, or the system hit its open-file limit. This guide explains what produces these errors, how to read the wrapped errno, and the fixes that apply across tools like nginx, sops, argo-workflows, and Pulumi.

Distilled from 107 documented records across 42 repositories.

Background

This family is produced at the boundary between application code and the operating system: a library or daemon calls open(), fopen(), os.Open, or File::open and the syscall returns an error. Unlike a parse error or a network failure, nothing about the request itself is wrong — the program could not get a file descriptor, so the operation aborts before any reading or writing begins. Well-built wrappers preserve the OS-level cause: nginx maps errno directly to a log level and HTTP status (EACCES → 403, ENOENT-family → 404, else 500); Go code wraps the error with %w so errors.Is(err, fs.ErrNotExist) and fs.ErrPermission still work; Rust and PHP embed the cause text after the path in the message. Reading that wrapped errno is always the first diagnostic step, because it selects the fix.

A few errnos dominate across the records. ENOENT means the path does not exist — sometimes a genuine misconfiguration, sometimes expected behavior (nginx's gzip_static probes for .gz twins that may legitimately be missing; try_files deliberately falls through to the next candidate). EACCES means the process user cannot read or traverse the path — files need the read bit, and every parent directory needs search (o+x) permission, which is why chown/chmod and SELinux/AppArmor label fixes (restorecon) recur in almost every solution set. EISDIR and ENOTDIR mean the path is (or passes through) a directory where a file was expected. EMFILE/ENFILE and ELOOP round out the family: fd exhaustion in long-running daemons like Weaviate and containerd, and symlink cycles in deployed trees.

From the caller's side the error looks different depending on where the open happens. Some libraries open files lazily, so the failure surfaces far from the code that requested it: googleworkspace/cli opens the upload file inside the streamed request body, so the error appears during reqwest .send() rather than at argument parsing; VictoriaMetrics opens snapshot part files inside parallel upload workers. Others validate first and open second, which introduces a check-then-open race: Intervention/image passes a readability pre-check but can still fail in fopen() because another process unlinked the file in between. Many tools also use open not only for reading inputs but for creating outputs — Pulumi stack export --file, delve breakpoints -save, and Hubble's flow exporter all fail this way when the destination directory is missing, unwritable, or read-only, which is why the same family covers both 'cannot read input' and 'cannot create output' failures.

The surrounding discipline is similar everywhere. Distinguish expected ENOENT (optional files, precompressed twins, tolerated absent outputs — argo-workflows explicitly treats missing output parameters as nil with a warning) from real failures (EACCES, EIO, ENOSPC), which indicate permissions, storage health, or capacity problems. Watch for races where files are deleted or permissions change between a stat/listing and the open — backup tools racing snapshot deletion, downloaders whose partial file got locked by antivirus, containerd losing a file between stat and open. And in containerized or CI environments, remember the extra failure modes: read-only root filesystems, missing volume mounts, open_basedir in PHP, umask on files generated as root, and relative paths resolving against a different working directory.

Common causes

What usually fixes it

Documented occurrences

…and 87 more across the corpus — use search.

Honest provenance: generated on 2026-09-05 from AI-assisted analysis of the linked records. See how records are made.