{"record":{"id":"c3ff1a647c6e5221","repo":"coreybutler/nvm-windows","slug":"failed-to-set-file-permissions-v","errorCode":null,"errorMessage":"failed to set file permissions: %v","messagePattern":"failed to set file permissions: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/upgrade/upgrade.go","lineNumber":949,"sourceCode":"\t\treturn fmt.Errorf(\"failed to create destination file: %v\", err)\n\t}\n\tdefer destinationFile.Close()\n\n\t// Copy contents from the source file to the destination file\n\t_, err = io.Copy(destinationFile, sourceFile)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to copy file: %v\", err)\n\t}\n\n\t// Optionally, copy file permissions (this can be skipped if not needed)\n\tsourceInfo, err := os.Stat(src)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to get source file info: %v\", err)\n\t}\n\n\terr = os.Chmod(dst, sourceInfo.Mode())\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to set file permissions: %v\", err)\n\t}\n\n\treturn nil\n}\n\n// copyDirContents copies all the contents (files and subdirectories) of a source directory to a destination directory.\nfunc copyDirContents(srcDir, dstDir string) error {\n\t// Ensure destination directory exists\n\terr := os.MkdirAll(dstDir, 0755)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to create destination directory %s: %v\", dstDir, err)\n\t}\n\n\t// Walk through the source directory recursively\n\terr = filepath.Walk(srcDir, func(srcPath string, info os.FileInfo, err error) error {\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error accessing %s: %v\", srcPath, err)\n\t\t}","sourceCodeStart":931,"sourceCodeEnd":967,"githubUrl":"https://github.com/coreybutler/nvm-windows/blob/5b18223ca19ff50d707f35410dbc6bd440a9f74d/src/upgrade/upgrade.go#L931-L967","documentation":"copyFile's final step applies the source file's permission bits to the destination with os.Chmod, and this error means that failed. On Windows, Chmod maps to SetFileInformationByHandle and can be denied when the destination handle is still open (the deferred Close has not run yet) or when ACLs on the destination forbid the change. The data copy itself already succeeded, so the file exists but may carry default permissions.","triggerScenarios":"Destination under a directory with restrictive ACLs (Program Files without elevation); the still-open destinationFile handle conflicting with the mode change; read-only attribute on the destination inherited from the directory.","commonSituations":"Non-admin installs into protected paths; group-policy ACL inheritance marking files read-only; enterprise lockdown tools reverting permission changes.","solutions":["Run the upgrade elevated so permission changes under NVM_HOME succeed.","Check inherited ACLs/attributes on the destination directory (attrib -r, icacls) and clear read-only inheritance.","Treat as non-fatal if present: the copied bytes are valid; re-running as admin fixes modes."],"exampleFix":"// before\nerr = os.Chmod(dst, sourceInfo.Mode())\nif err != nil {\n    return fmt.Errorf(\"failed to set file permissions: %v\", err)\n}\n\n// after: close handles before chmod and tolerate failure on Windows\ndestinationFile.Close()\nsourceFile.Close()\nif err := os.Chmod(dst, sourceInfo.Mode()); err != nil {\n    // permissions are advisory on Windows; log but do not fail the copy\n    utility.DebugLogf(\"chmod %s: %v\", dst, err)\n}","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"Permission mirroring is optional: catch the Chmod error, log it, and return nil so the copied file is used as-is. Only fail when a later exec of the copied binary proves permissions actually matter.","preventionTips":["Close destination handles before chmod.","Run elevated when installing into ACL-protected trees.","Remember Windows modes are advisory; don't hard-fail on them."],"tags":["filesystem","permissions","windows"],"backgroundTag":null,"analyzedSha":"5b18223ca19ff50d707f35410dbc6bd440a9f74d","analyzedAt":"2026-08-15T10:06:51.428Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}