hashicorp/nomad · error
Couldn't create destination directory %v: %w
Error message
Couldn't create destination directory %v: %w
What it means
embedDirs, called from buildChroot, embeds host files into the chroot task directory. When a chroot mapping entry is a single file, it first creates the destination directory inside t.Dir via createDir. This error wraps createDir's failure, reported with the destination path. It aborts chroot construction for the alloc.
Source
Thrown at client/allocdir/task_dir.go:242
func (t *TaskDir) embedDirs(entries map[string]string) error {
subdirs := make(map[string]string)
for source, dest := range entries {
if t.skip.Contains(source) {
// source in skip list
continue
}
// Check to see if directory exists on host.
s, err := os.Stat(source)
if os.IsNotExist(err) {
continue
}
// Embedding a single file
if !s.IsDir() {
if err := createDir(t.Dir, filepath.Dir(dest)); err != nil {
return fmt.Errorf("Couldn't create destination directory %v: %w", dest, err)
}
// Copy the file.
taskEntry := filepath.Join(t.Dir, dest)
uid, gid := getOwner(s)
if err := linkOrCopy(source, taskEntry, uid, gid, s.Mode().Perm()); err != nil {
return err
}
continue
}
// Create destination directory.
destDir := filepath.Join(t.Dir, dest)
if err := createDir(t.Dir, dest); err != nil {
return fmt.Errorf("Couldn't create destination directory %v: %w", destDir, err)
}View on GitHub (pinned to 482b49bf1a)
Solutions
- Read the wrapped OS error: EEXIST/ENOTDIR → delete the conflicting file at the destination inside the task dir; ENOSPC → free disk space; EACCES → fix data_dir ownership
- Clean the task dir for the failing alloc and restart it (`rm -rf <data_dir>/<alloc>/<task>` with client stopped)
- Check the task's chroot mapping in the client config for duplicate/conflicting destination paths
- Confirm the nomad user can write t.Dir
Example fix
# before Couldn't create destination directory etc/ssl/certs: mkdir /var/nomad/.../etc/ssl/certs: not a directory # after $ ls -ld /var/nomad/<alloc>/<task>/etc/ssl/certs # it's a file $ rm /var/nomad/<alloc>/<task>/etc/ssl/certs $ nomad alloc restart <alloc>
Defensive patterns
Strategy: validation
Validate before calling
// pre-check chroot destination inside task dir isn't occupied by a file
for _, dest := range chrootMap {
p := filepath.Join(taskDir, filepath.Dir(dest))
if fi, err := os.Stat(p); err == nil && !fi.IsDir() {
os.RemoveAll(p) // or fail fast with a clear message
}
} Try / catch
if err := taskDir.Build(fsi, chroot, username); err != nil {
var e *fmt.Errorf
if errors.As(err, &e) && strings.Contains(err.Error(), "Couldn't create destination directory") {
// inspect wrapped errno: ENOSPC → free space; ENOTDIR → clean task dir; then retry
return retryAfterClean(taskDir, err)
}
return err
} Prevention
- Monitor data_dir free space
- Don't map the same destination to both a file and a directory in chroot config
- Reset the task dir when restarting an alloc after config changes
- Keep data_dir owned by the nomad user
When it happens
Trigger: TaskDir.buildChroot processing a chroot map entry whose source is a file, and createDir(t.Dir, filepath.Dir(dest)) fails — e.g. a non-directory exists at the parent path inside the task dir, or the task dir is unwritable.
Common situations: data_dir on a full/read-only disk; previous task run left a file where a chroot destination directory must be; chroot map entry with conflicting paths (same dest as both file and directory from config); permissions on the nomad data dir changed.
Related errors
- Couldn't create symlink: %w
- plugin not executable
- failed to snapshot %s: %w
- error creating task %q dir: %w
- Couldn't open src file %v: %w
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/8ae6a41db4601237.
Report an issue: GitHub.