kovidgoyal/kitty · warning
computing relative path: %w
Error message
computing relative path: %w
What it means
RelativeIfUnder finishes with filepath.Rel(base, target), which computes the relative path. Rel can only fail when it cannot make target relative to base — on Windows when the paths are on different volumes (e.g. C:\ vs D:\); on Unix this is practically unreachable because Abs+Clean normalizes both.
Source
Thrown at tools/utils/paths.go:374
// Make absolute and clean
if base, err = filepath.Abs(base); err != nil {
return "", false, fmt.Errorf("abs base: %w", err)
}
if target, err = filepath.Abs(target); err != nil {
return "", false, fmt.Errorf("abs target: %w", err)
}
// On Windows the volume (drive letter) must match. If they don't, the path is not inside.
if runtime.GOOS == "windows" {
if !strings.EqualFold(filepath.VolumeName(base), filepath.VolumeName(target)) {
return "", false, nil
}
}
// Get the relative path from base to target
rel, err = filepath.Rel(base, target)
if err != nil {
return "", false, fmt.Errorf("computing relative path: %w", err)
}
// If rel begins with ".." (or is ".."), then target is outside base.
// Use os.PathSeparator to be portable.
up := ".." + string(os.PathSeparator)
if rel == ".." || strings.HasPrefix(rel, up) {
return "", false, nil
}
// If the returned rel is empty (shouldn't normally happen), normalize to "."
if rel == "" {
rel = "."
}
return rel, true, nil
}
View on GitHub (pinned to 6d5d0c4406)
Solutions
- Guard on Windows by comparing filepath.VolumeName(base) and VolumeName(target) first.
- Map both paths to a common volume (subst/junction) before comparison.
- Treat this error as "not inside" and skip the relative-path optimization for that target.
- Report both paths in logs to identify the volume mismatch.
Example fix
// before
rel, inside, err := utils.RelativeIfUnder(base, target, false)
// after
rel, inside, err := utils.RelativeIfUnder(base, target, false)
if err != nil { // e.g. cross-volume on Windows
rel, inside, err = target, false, nil
} Defensive patterns
Strategy: fallback
Validate before calling
if runtime.GOOS == "windows" && !strings.EqualFold(filepath.VolumeName(base), filepath.VolumeName(target)) {
// skip relative-path handling; different volumes
} Try / catch
rel, inside, err := utils.RelativeIfUnder(base, target, false)
if err != nil {
rel, inside = "", false // treat as outside base; use absolute target
} Prevention
- Compare volume names on Windows before calling.
- Map both paths to a common drive or UNC root.
- Log base and target when Rel fails to spot volume mismatches.
When it happens
Trigger: Windows-only: base and target on different drive letters after volume-name check passes (e.g. UNC vs lettered drive mixtures), causing filepath.Rel to return an error.
Common situations: Cross-drive comparisons on Windows, e.g. base under C:\Users and target as a UNC \\server\share path.
Related errors
- resolving base symlinks: %w
- resolving target symlinks: %w
- abs base: %w
- abs target: %w
- Too much piped data
AI-assisted analysis of kovidgoyal/kitty@6d5d0c4406 (2026-08-27).
Data as JSON: /api/errors/382c3795750aa664.
Report an issue: GitHub.