hashicorp/nomad · error
error opening fifo parent directory %q: %w
Error message
error opening fifo parent directory %q: %w
What it means
fifo.OpenReader opens the parent directory of the FIFO with os.OpenRoot before opening the FIFO itself, using openat2 with O_NOFOLLOW protections. This error wraps a failure opening the FIFO's parent directory, so the reader function cannot even attempt to open the FIFO.
Source
Thrown at client/lib/fifo/fifo_unix.go:38
// so it's advised to run it in a goroutine different from reader goroutine
func CreateAndRead(path string) (func() (io.ReadCloser, error), error) {
// create first
if err := mkfifo(path, 0600); err != nil {
return nil, fmt.Errorf("error creating fifo %v: %w", path, err)
}
return func() (io.ReadCloser, error) {
return OpenReader(path)
}, nil
}
func OpenReader(path string) (io.ReadCloser, error) {
dir := filepath.Dir(path)
base := filepath.Base(path)
root, err := os.OpenRoot(dir)
if err != nil {
return nil, fmt.Errorf("error opening fifo parent directory %q: %w", dir, err)
}
defer root.Close()
// also uses O_NOFOLLOW under the hood
f, err := root.OpenFile(base, os.O_RDONLY, 0)
if err != nil {
return nil, fmt.Errorf("error opening reader at %s: %w", path, err)
}
return f, nil
}
// OpenWriter opens a fifo file for writer, assuming it already exists, returns io.WriteCloser
func OpenWriter(path string) (io.WriteCloser, error) {
dir := filepath.Dir(path)
base := filepath.Base(path)
root, err := os.OpenRoot(dir)
if err != nil {View on GitHub (pinned to 482b49bf1a)
Solutions
- Re-run the open after confirming the alloc directory exists — if the allocation was GC'd, re-create the logs directory or restart the task.
- Fix ownership/permissions on the alloc logs directory so the Nomad agent user can read it (e.g. chown -R nomad:nomad).
- Verify the path component is a real directory, not a file or dangling symlink.
- Check client data_dir for corruption; run nomad fs/alloc inspection or restart the client to rebuild alloc dirs.
Example fix
// before: dir removed under the reader // EACCES on /var/lib/nomad/alloc/.../alloc/logs // after $ sudo chown -R nomad:nomad /var/lib/nomad/alloc $ nomad alloc logs <alloc_id>
Defensive patterns
Strategy: try-catch
Validate before calling
func fifoDirReadable(path string) error {
dir := filepath.Dir(path)
st, err := os.Stat(dir)
if err != nil { return err }
if !st.IsDir() { return fmt.Errorf("%s is not a directory", dir) }
return syscall.Access(dir, syscall.R_OK)
} Type guard
func fifoDirReady(path string) bool {
st, err := os.Stat(filepath.Dir(path))
return err == nil && st.IsDir() && syscall.Access(filepath.Dir(path), syscall.R_OK) == nil
} Try / catch
r, err := fifo.OpenReader(path)
if err != nil {
var perr *fs.PathError
if errors.As(err, &perr) && errors.Is(perr.Err, syscall.ENOENT) {
// alloc was GC'd mid-read: recreate dir and retry once
os.MkdirAll(filepath.Dir(path), 0755)
r, err = fifo.OpenReader(path)
}
if err != nil { return nil, err }
} Prevention
- Stop log followers before draining/GC'ing the allocation.
- Keep alloc/logs directories owned by the Nomad agent user with readable permissions.
- Verify the path is a directory, not a replaced file or dangling symlink.
- Monitor client GC activity if log streaming is interrupted mid-read.
When it happens
Trigger: os.OpenRoot(dir) fails inside OpenReader because the directory does not exist (ENOENT — alloc dir cleaned up while reading), permissions deny access (EACCES), or path is not a directory (ENOTDIR, e.g. a file replaced the directory).
Common situations: Following Nomad logs while the allocation is garbage-collected concurrently; permissions on the alloc/logs directory changed (chmod/chown by operator); symlink or file substituted for the logs directory; NFS/overlay quirks returning unexpected errors.
Related errors
- error creating fifo %v: %w
- failed to create fifo for extracting logs: %v
- Couldn't change owner/group of %v to (uid: %v, gid: %v): %w
- Couldn't resolve symlink for %v: %w
- Failed to delete proc directory %q: %w
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/7bc411f92e49e35d.
Report an issue: GitHub.