coreybutler/nvm-windows · error
failed to get relative path for %s: %v
Error message
failed to get relative path for %s: %v
What it means
Inside the copyDirContents walk callback, filepath.Rel(srcDir, srcPath) computes the destination-relative path and this error means that call failed. In practice Rel fails only when srcDir and srcPath cannot be related — one is absolute and the other relative, or a volume separator mismatch (C: vs D:) sneaks in. Within the documented flow it is near-unreachable; when seen, it indicates malformed path inputs (UNC vs drive-letter mixing, empty srcDir) rather than an environment problem.
Source
Thrown at src/upgrade/upgrade.go:972
// copyDirContents copies all the contents (files and subdirectories) of a source directory to a destination directory.
func copyDirContents(srcDir, dstDir string) error {
// Ensure destination directory exists
err := os.MkdirAll(dstDir, 0755)
if err != nil {
return fmt.Errorf("failed to create destination directory %s: %v", dstDir, err)
}
// Walk through the source directory recursively
err = filepath.Walk(srcDir, func(srcPath string, info os.FileInfo, err error) error {
if err != nil {
return fmt.Errorf("error accessing %s: %v", srcPath, err)
}
// Construct the corresponding path in the destination directory
relPath, err := filepath.Rel(srcDir, srcPath)
if err != nil {
return fmt.Errorf("failed to get relative path for %s: %v", srcPath, err)
}
dstPath := filepath.Join(dstDir, relPath)
// If it's a directory, ensure it's created in the destination
if info.IsDir() {
return os.MkdirAll(dstPath, info.Mode())
}
// If it's a file, copy it
return copyFile(srcPath, dstPath)
})
return err
}
// zipDirectory zips the contents of a directory.
func zipDirectory(sourceDir, outputZip string) error {View on GitHub (pinned to 5b18223ca1)
Solutions
- Normalize both srcDir and the walk root to absolute cleaned paths with filepath.Abs/filepath.Clean before walking.
- Avoid UNC paths for NVM_HOME; map the share to a drive letter or use a local directory.
- Log srcDir and the failing srcPath at error time (add them to the message) to confirm the mismatch.
- Retry after relocating the operation to a local filesystem path.
Example fix
// before
relPath, err := filepath.Rel(srcDir, srcPath)
// after: normalize the base once, outside the callback
srcRoot, err := filepath.Abs(srcDir)
if err != nil { return err }
...
relPath, err := filepath.Rel(srcRoot, srcPath)
if err != nil {
return fmt.Errorf("failed to get relative path for %s under %s: %v", srcPath, srcRoot, err)
} Defensive patterns
Strategy: validation
Validate before calling
// Normalize the walk root once, and reject un-relatable inputs
srcRoot, err := filepath.Abs(srcDir)
if err != nil || srcRoot == "" {
return fmt.Errorf("invalid source dir: %q", srcDir)
}
// later: filepath.Rel(srcRoot, filepath.Clean(srcPath)) Try / catch
This is a programming-error class failure: catch, include both paths in the message, and stop — retrying cannot fix mismatched path forms. Fix the caller to pass normalized absolute paths.
Prevention
- Always filepath.Abs both sides before walking.
- Avoid UNC/mixed drive-letter path forms for NVM_HOME.
- Reject empty or volume-relative path inputs early.
When it happens
Trigger: srcDir passed as a UNC path (\\server\share) while Walk yields drive-letter paths or vice versa; srcDir empty or relative while Walk returns absolute paths; volume-relative paths (C:foo without a slash) appearing in the tree; cwd changing mid-walk.
Common situations: NVM_HOME configured as a UNC/network path so extracted paths and base path disagree; manually invoking the copy routine with mismatched path forms; exotic junction/symlink layouts inside the extracted tree.
Related errors
- error: failed to create backup directory: %v
- error: failed to copy update.exe: %v
- failed to open source file: %v
- failed to create destination file: %v
- failed to create destination directory %s: %v
AI-assisted analysis of coreybutler/nvm-windows@5b18223ca1 (2026-08-15).
Data as JSON: /api/errors/b80ed7163587c7ee.
Report an issue: GitHub.