hashicorp/nomad · error
error creating symlink: %w
Error message
error creating symlink: %w
What it means
When extracting a symlink entry from the alloc dir tar archive, os.Symlink(hdr.Linkname, dest/hdr.Name) failed. This can happen if the target path already exists, the parent directory is missing, or the filesystem forbids symlinks.
Source
Thrown at client/allocwatcher/alloc_watcher.go:630
}
// If the header is for a directory we create the directory
if hdr.Typeflag == tar.TypeDir {
name := filepath.Join(dest, hdr.Name)
os.MkdirAll(name, os.FileMode(hdr.Mode))
// Can't change owner if not root or on Windows.
if euid == 0 {
if err := os.Chown(name, hdr.Uid, hdr.Gid); err != nil {
return fmt.Errorf("error chowning directory %w", err)
}
}
continue
}
// If the header is for a symlink we create the symlink
if hdr.Typeflag == tar.TypeSymlink {
if err = os.Symlink(hdr.Linkname, filepath.Join(dest, hdr.Name)); err != nil {
return fmt.Errorf("error creating symlink: %w", err)
}
for _, path := range []string{hdr.Name, hdr.Linkname} {
if escapes, err := escapingfs.PathEscapesAllocDir(dest, "", path); err != nil {
return fmt.Errorf("error evaluating symlink: %w", err)
} else if escapes {
return fmt.Errorf("archive contains symlink that escapes alloc dir")
}
}
continue
}
// If the header is a file, we write to a file
if hdr.Typeflag == tar.TypeReg {
fPath := filepath.Join(dest, hdr.Name)
if _, err := os.Lstat(fPath); err == nil {
if err := os.Remove(fPath); err != nil {
return fmt.Errorf("error removing existing file: %w", err)View on GitHub (pinned to 482b49bf1a)
Solutions
- Remove any pre-existing file/dir at the destination path before extraction
- Ensure the parent directory for the symlink was created earlier in the archive
- On Windows, run the client with SeCreateSymbolicLinkPrivilege
- Verify the alloc dir filesystem permits symlink creation
Example fix
// before
if err = os.Symlink(hdr.Linkname, filepath.Join(dest, hdr.Name)); err != nil {
return fmt.Errorf("error creating symlink: %w", err)
}
// after
linkPath := filepath.Join(dest, hdr.Name)
if _, err := os.Lstat(linkPath); err == nil {
os.Remove(linkPath)
}
if err = os.Symlink(hdr.Linkname, linkPath); err != nil {
return fmt.Errorf("error creating symlink: %w", err)
} Defensive patterns
Strategy: validation
Validate before calling
// Pre-check the destination path is clear and FS supports symlinks:
// link := filepath.Join(dest, "__probe__"); os.Symlink(".", link); os.Remove(link) Try / catch
if err := watcher.Wait(ctx); err != nil {
if strings.Contains(err.Error(), "error creating symlink") {
// clean stale extraction dir and retry
os.RemoveAll(dest)
return retryMigration(ctx, alloc)
}
return err
} Prevention
- Clean partially extracted alloc dirs before retrying migrations
- Grant symlink privileges on Windows (developer mode or SeCreateSymbolicLinkPrivilege)
- Use filesystems that allow symlinks for the client data dir
When it happens
Trigger: streamAllocDir processes a tar.TypeSymlink header and the symlink creation syscall returns an error (EEXIST, ENOENT on parent, EPERM on symlink-restricted filesystems).
Common situations: Stale file already at the destination path from an earlier extraction; Windows without symlink privilege; filesystems mounted with symlinks disabled; duplicate entries in the archive.
Related errors
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/d4f212832ffd152b.
Report an issue: GitHub.