{"record":{"id":"d4f212832ffd152b","repo":"hashicorp/nomad","slug":"error-creating-symlink-w","errorCode":null,"errorMessage":"error creating symlink: %w","messagePattern":"error creating symlink: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/allocwatcher/alloc_watcher.go","lineNumber":630,"sourceCode":"\t\t}\n\n\t\t// If the header is for a directory we create the directory\n\t\tif hdr.Typeflag == tar.TypeDir {\n\t\t\tname := filepath.Join(dest, hdr.Name)\n\t\t\tos.MkdirAll(name, os.FileMode(hdr.Mode))\n\n\t\t\t// Can't change owner if not root or on Windows.\n\t\t\tif euid == 0 {\n\t\t\t\tif err := os.Chown(name, hdr.Uid, hdr.Gid); err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"error chowning directory %w\", err)\n\t\t\t\t}\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\t// If the header is for a symlink we create the symlink\n\t\tif hdr.Typeflag == tar.TypeSymlink {\n\t\t\tif err = os.Symlink(hdr.Linkname, filepath.Join(dest, hdr.Name)); err != nil {\n\t\t\t\treturn fmt.Errorf(\"error creating symlink: %w\", err)\n\t\t\t}\n\n\t\t\tfor _, path := range []string{hdr.Name, hdr.Linkname} {\n\t\t\t\tif escapes, err := escapingfs.PathEscapesAllocDir(dest, \"\", path); err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"error evaluating symlink: %w\", err)\n\t\t\t\t} else if escapes {\n\t\t\t\t\treturn fmt.Errorf(\"archive contains symlink that escapes alloc dir\")\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcontinue\n\t\t}\n\t\t// If the header is a file, we write to a file\n\t\tif hdr.Typeflag == tar.TypeReg {\n\t\t\tfPath := filepath.Join(dest, hdr.Name)\n\t\t\tif _, err := os.Lstat(fPath); err == nil {\n\t\t\t\tif err := os.Remove(fPath); err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"error removing existing file: %w\", err)","sourceCodeStart":612,"sourceCodeEnd":648,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/client/allocwatcher/alloc_watcher.go#L612-L648","documentation":"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.","triggerScenarios":"streamAllocDir processes a tar.TypeSymlink header and the symlink creation syscall returns an error (EEXIST, ENOENT on parent, EPERM on symlink-restricted filesystems).","commonSituations":"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.","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"],"exampleFix":"// before\nif err = os.Symlink(hdr.Linkname, filepath.Join(dest, hdr.Name)); err != nil {\n    return fmt.Errorf(\"error creating symlink: %w\", err)\n}\n// after\nlinkPath := filepath.Join(dest, hdr.Name)\nif _, err := os.Lstat(linkPath); err == nil {\n    os.Remove(linkPath)\n}\nif err = os.Symlink(hdr.Linkname, linkPath); err != nil {\n    return fmt.Errorf(\"error creating symlink: %w\", err)\n}","handlingStrategy":"validation","validationCode":"// Pre-check the destination path is clear and FS supports symlinks:\n// link := filepath.Join(dest, \"__probe__\"); os.Symlink(\".\", link); os.Remove(link)","typeGuard":null,"tryCatchPattern":"if err := watcher.Wait(ctx); err != nil {\n    if strings.Contains(err.Error(), \"error creating symlink\") {\n        // clean stale extraction dir and retry\n        os.RemoveAll(dest)\n        return retryMigration(ctx, alloc)\n    }\n    return err\n}","preventionTips":["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"],"tags":["nomad","filesystem","symlink","extract"],"backgroundTag":"symlink-creation-failed","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}