hashicorp/nomad · error

failed to create file %q, err: %w

Error message

failed to create file %q, err: %w

What it means

Thrown by `writeBytes` when `os.Create(filePath)` fails after the sandbox check has passed, meaning the file could not be opened for writing. Nomad wraps the OS error (permission denied, too many open files, is-a-directory, no space left) with the full file path.

Source

Thrown at command/operator_debug.go:1417

	dirPath := filepath.Join(c.collectDir, dir)
	filePath := filepath.Join(dirPath, filename)

	// Ensure parent directories exist
	err := escapingfs.EnsurePath(dirPath, true)
	if err != nil {
		return fmt.Errorf("failed to create parent directories of %q: %w", dirPath, err)
	}

	// Ensure filename doesn't escape the sandbox of the capture directory
	escapes := escapingfs.PathEscapesSandbox(c.collectDir, filePath)
	if escapes {
		return fmt.Errorf("file path %q escapes capture directory %q", filePath, c.collectDir)
	}

	// Create the file
	fh, err := os.Create(filePath)
	if err != nil {
		return fmt.Errorf("failed to create file %q, err: %w", filePath, err)
	}
	defer fh.Close()

	_, err = fh.Write(data)
	if err != nil {
		return fmt.Errorf("Failed to write data to file %q, err: %w", filePath, err)
	}
	return nil
}

// newFilePath returns a validated filepath rooted in the provided directory and
// path. It has been checked that it falls inside the sandbox and has been added
// to the manifest tracking.
func (c *OperatorDebugCommand) newFilePath(dir, file string) (string, error) {

	// Replace invalid characters in filename
	filename := helper.CleanFilename(file, "_")

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Read the wrapped OS error: EACCES → fix permissions on collectDir; EISDIR → remove the directory at that filename; EMFILE → raise `ulimit -n`.
  2. Check free disk space (`df -h`) — ENOSPC produces this error.
  3. Re-run the debug command as a user with write access to the -output directory.
  4. Check for fd leaks in long-lived processes performing many captures (`lsof -p <pid> | wc -l`).

Example fix

// before (shell)
nomad operator debug -output /var/lib/nomad/debug   # root-owned
// after
sudo chown $(id -u):$(id -g) /var/lib/nomad/debug && nomad operator debug -output /var/lib/nomad/debug
Defensive patterns

Strategy: try-catch

Validate before calling

if info, err := os.Stat(targetPath); err == nil && info.IsDir() {
    return fmt.Errorf("target %q is a directory", targetPath)
}
probe := filepath.Join(collectDir, ".write-test")
if err := os.WriteFile(probe, nil, 0o600); err != nil {
    return fmt.Errorf("collect dir not writable: %w", err)
}
os.Remove(probe)

Try / catch

if err := c.writeBytes(dir, filename, resp, respErr); err != nil {
    var pe *fs.PathError
    if errors.As(err, &pe) && errors.Is(pe.Err, syscall.EMFILE) {
        // raise open-file limit or serialize captures
    }
    c.writeError(dir, err)
}

Prevention

When it happens

Trigger: os.Create failure inside the capture directory: permissions deny the user write access even though dirs were created, a directory already exists with the target filename, ulimit -n exhausted (too many open files), or disk full.

Common situations: Debug run as non-privileged user into a root-owned capture dir; long-running debug collections leaking file descriptors until EMFILE hits; a stale directory named like the expected capture file.

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/fdd389fe8afc5273. Report an issue: GitHub.