{"record":{"id":"594781330301cbd4","repo":"hashicorp/nomad","slug":"error-removing-existing-file-w","errorCode":null,"errorMessage":"error removing existing file: %w","messagePattern":"error removing existing file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/allocwatcher/alloc_watcher.go","lineNumber":648,"sourceCode":"\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)\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)","sourceCodeStart":630,"sourceCodeEnd":666,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/client/allocwatcher/alloc_watcher.go#L630-L666","documentation":"When extracting a regular file entry, Nomad removes any existing file at the destination path before creating a new one. This error is returned when os.Remove on the pre-existing path fails, e.g. due to permissions or the path being a non-empty directory.","triggerScenarios":"os.Lstat(fPath) succeeds (something already exists) and os.Remove(fPath) returns an error during TypeReg extraction.","commonSituations":"Destination path is a non-empty directory where the archive expects a file (EISDIR/ENOTEMPTY); files owned by another UID; read-only mount; leftover state from a failed previous extraction.","solutions":["Inspect the destination path — if it is a directory, clear it or fix the archive layout","Fix ownership/permissions on stale files in the alloc dir (run as root or chown manually)","Clean the partially extracted destination dir and retry the migration","Ensure the alloc dir is not mounted read-only"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Before migration, check the destination dir has no stale path where a file is expected:\n// if fi, err := os.Lstat(p); err == nil && fi.IsDir() { clean up or resolve conflict }","typeGuard":null,"tryCatchPattern":"if err := watcher.Wait(ctx); err != nil {\n    if strings.Contains(err.Error(), \"error removing existing file\") {\n        os.RemoveAll(dest)\n        return retryMigration(ctx, alloc)\n    }\n    return err\n}","preventionTips":["Clean leftover state from failed extractions before retrying","Run the Nomad client with ownership of its data dir","Never mount the alloc dir read-only"],"tags":["nomad","filesystem","file-extraction","permissions"],"backgroundTag":"file-remove-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"}