{"record":{"id":"fc8f9d9587f09b5a","repo":"hasura/graphql-engine","slug":"error-cleaning-up-dir-q-w","errorCode":null,"errorMessage":"error cleaning up dir %q: %w","messagePattern":"error cleaning up dir %q: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cli/plugins/move.go","lineNumber":259,"sourceCode":"\t}\n\n\treturn nil\n}\n\n// renameOrCopy will try to rename a dir or file. If rename is not supported, a manual copy will be performed.\n// Existing files at \"to\" will be deleted.\nfunc renameOrCopy(from, to string) error {\n\tvar op errors.Op = \"plugins.renameOrCopy\"\n\n\tfi, err := os.Stat(to)\n\tif err != nil && !stderrors.Is(err, fs.ErrNotExist) {\n\t\treturn errors.E(op, fmt.Errorf(\"error checking move target dir %q: %w\", to, err))\n\t}\n\n\tif fi != nil && fi.IsDir() {\n\t\terr := os.RemoveAll(to)\n\t\tif err != nil {\n\t\t\treturn errors.E(op, fmt.Errorf(\"error cleaning up dir %q: %w\", to, err))\n\t\t}\n\t}\n\n\terr = os.Rename(from, to)\n\t// Fallback for invalid cross-device link (errno:18).\n\tif isCrossDeviceRenameErr(err) {\n\t\tcopyErr := copyTree(from, to)\n\t\tif copyErr != nil {\n\t\t\treturn errors.E(\n\t\t\t\top,\n\t\t\t\tfmt.Errorf(\"failed to copy directory tree as a fallback: %w\", copyErr),\n\t\t\t)\n\t\t}\n\n\t\treturn nil\n\t}\n\n\tif err != nil {","sourceCodeStart":241,"sourceCodeEnd":277,"githubUrl":"https://github.com/hasura/graphql-engine/blob/724551b9ae87845594ef0408cff0e50eb6c90dc5/cli/plugins/move.go#L241-L277","documentation":"renameOrCopy found that the destination already exists as a directory and os.RemoveAll(to) failed while trying to clear it before the rename. The old install directory could not be deleted, so it cannot be replaced.","triggerScenarios":"The destination directory exists and RemoveAll fails: files inside are owned by another user/root, the filesystem is read-only, a file is locked (Windows), or an I/O error occurs mid-delete.","commonSituations":"Upgrading a plugin whose earlier install was done with sudo (root-owned files); Windows AV/indexer holding handles; read-only container volume for the plugins dir.","solutions":["Inspect ownership of the destination dir quoted in the error; chown -R to the current user or remove with appropriate privileges","Close processes/AV locks on Windows; retry after they release","Remount or relocate the plugins dir to a writable filesystem","Manually remove the stale install dir and re-run the install"],"exampleFix":"# before\nsudo rm -rf ~/.local/share/hasura/plugins  # then still root? no:\n# after\nsudo chown -R $(id -u) ~/.local/share/hasura/plugins\nhasura plugins install my-plugin","handlingStrategy":"try-catch","validationCode":"if fi, err := os.Stat(to); err == nil && fi.IsDir() {\n    if err := os.RemoveAll(to); err != nil { return fmt.Errorf(\"pre-clean failed: %w\", err) }\n}","typeGuard":null,"tryCatchPattern":"if err := moveToInstallDir(...); err != nil && strings.Contains(err.Error(), \"cleaning up dir\") {\n    // chown -R the target dir to the user, remove manually, retry install\n}","preventionTips":["Never install plugins with sudo then upgrade without it","Close AV/locking software interfering with the plugins dir on Windows","Periodically audit ownership of the plugins tree"],"tags":["go","filesystem","permissions","cleanup"],"backgroundTag":"removeall-permission-denied","analyzedSha":"724551b9ae87845594ef0408cff0e50eb6c90dc5","analyzedAt":"2026-08-28T07:32:55.105Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}