hashicorp/nomad · error

Couldn't create destination file %v: %w

Error message

Couldn't create destination file %v: %w

What it means

fileCopy() creates the destination with os.OpenFile(dst, O_WRONLY|O_CREATE, perm). Failure is wrapped as "Couldn't create destination file". This means the copy target could not be created or opened for writing in the alloc/task dir tree.

Source

Thrown at client/allocdir/alloc_dir.go:574

// getFileWatcher returns a FileWatcher for the given path.
func getFileWatcher(path string) watch.FileWatcher {
	return watch.NewPollingFileWatcher(path)
}

// fileCopy from src to dst setting the permissions and owner (if uid & gid are
// both greater than 0)
func fileCopy(src, dst string, uid, gid int, perm os.FileMode) error {
	// Do a simple copy.
	srcFile, err := os.Open(src)
	if err != nil {
		return fmt.Errorf("Couldn't open src file %v: %w", src, err)
	}
	defer srcFile.Close()

	dstFile, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE, perm)
	if err != nil {
		return fmt.Errorf("Couldn't create destination file %v: %w", dst, err)
	}
	defer dstFile.Close()

	if _, err := io.Copy(dstFile, srcFile); err != nil {
		return fmt.Errorf("Couldn't copy %q to %q: %w", src, dst, err)
	}

	if uid != idUnsupported && gid != idUnsupported {
		if err := dstFile.Chown(uid, gid); err != nil {
			return fmt.Errorf("Couldn't copy %q to %q: %w", src, dst, err)
		}
	}

	return nil
}

// pathExists is a helper function to check if the path exists.
func pathExists(path string) bool {

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Ensure the destination's parent directory exists and is created with correct permissions first
  2. Check disk space (ENOSPC) and free space on the client volume
  3. Verify the destination path does not collide with an existing directory
  4. Run os.Chown/os.Chmod on the created file as needed (fileCopy only sets perm at create)

Example fix

// before
fileCopy(src, "task/web/no/such/dir/f", uid, gid, perm)
// after
os.MkdirAll(filepath.Dir(dst), 0755)
fileCopy(src, dst, uid, gid, perm)
Defensive patterns

Strategy: try-catch

Validate before calling

parent := filepath.Dir(dst)
if err := os.MkdirAll(parent, 0o755); err != nil {
    return fmt.Errorf("cannot create dst parent: %w", err)
}
if fi, err := os.Stat(dst); err == nil && fi.IsDir() {
    return fmt.Errorf("dst is a directory: %q", dst)
}

Try / catch

if err := linkOrCopy(src, dst, uid, gid, perm); err != nil {
    if errors.Is(err, syscall.ENOSPC) {
        // free disk space or move data_dir, then retry
    }
    return err
}

Prevention

When it happens

Trigger: Calling linkOrCopy/fileCopy where the destination path's parent does not exist, the destination is unwritable (permission denied), the disk is full, or the destination path is a directory.

Common situations: Task dir tree partially created before copy; ENOSPC on a full client volume; destination name collides with an existing directory; permission mismatch after user: changes in task config.

Related errors


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