{"record":{"id":"cbeb89e14cbcddab","repo":"hashicorp/nomad","slug":"error-chmoding-file-w","errorCode":null,"errorMessage":"error chmoding file %w","messagePattern":"error chmoding file %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/allocwatcher/alloc_watcher.go","lineNumber":659,"sourceCode":"\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)\n\t\t\t\t}\n\t\t\t}\n\t\t\tf, err := os.Create(fPath)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"error creating file: %w\", err)\n\t\t\t}\n\n\t\t\t// Setting the permissions of the file as the origin.\n\t\t\tif err := f.Chmod(os.FileMode(hdr.Mode)); err != nil {\n\t\t\t\tf.Close()\n\t\t\t\treturn fmt.Errorf(\"error chmoding file %w\", err)\n\t\t\t}\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 := f.Chown(hdr.Uid, hdr.Gid); err != nil {\n\t\t\t\t\tf.Close()\n\t\t\t\t\treturn fmt.Errorf(\"error chowning file %w\", err)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// We write in chunks so that we can test if the client\n\t\t\t// is still alive\n\t\t\tfor !canceled() {\n\t\t\t\tn, err := tr.Read(buf)\n\t\t\t\tif n > 0 && (err == nil || err == io.EOF) {\n\t\t\t\t\tif _, err := f.Write(buf[:n]); err != nil {\n\t\t\t\t\t\tf.Close()\n\t\t\t\t\t\treturn fmt.Errorf(\"error writing to file %q: %w\", f.Name(), err)","sourceCodeStart":641,"sourceCodeEnd":677,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/client/allocwatcher/alloc_watcher.go#L641-L677","documentation":"While streaming the previous allocation's directory as a tar archive in streamAllocDir, f.Chmod on a newly created regular file failed, aborting the migration of the alloc dir to the new node. The file is closed before returning so no descriptor leaks.","triggerScenarios":"os.Create succeeds but f.Chmod(hdr.Mode) returns an error during TypeReg extraction — e.g. read-only or special filesystems rejecting attribute changes, or fd issues.","commonSituations":"Files created on FAT/NTFS or other filesystems with limited permission support; security modules (SELinux/AppArmor) blocking chmod; unusual mode bits in a hand-crafted archive (e.g. setuid on restricted FS).","solutions":["Move the Nomad data dir onto a POSIX filesystem (ext4/xfs) instead of FAT/NTFS/network mounts","Check SELinux/AppArmor audit logs and add allow rules for the Nomad client","Inspect the archive header Mode values for unsupported bits","Retry the migration after fixing the destination filesystem"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Verify the destination filesystem supports chmod before placing the data dir:\n// f, _ := os.Create(probe); err := f.Chmod(0644); if err != nil { filesystem unsupported }","typeGuard":null,"tryCatchPattern":"if err := watcher.Wait(ctx); err != nil {\n    if strings.Contains(err.Error(), \"error chmoding file\") {\n        // fall back to a fresh alloc without migrating preserved permissions\n        return startWithoutMigration(ctx, alloc)\n    }\n    return err\n}","preventionTips":["Host the Nomad data dir on POSIX-permission filesystems","Avoid FAT/NTFS/9p mounts for client data dirs","Review SELinux/AppArmor policies for the Nomad client binary"],"tags":["nomad","filesystem","chmod","permissions"],"backgroundTag":"chmod-permission-denied","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}