{"record":{"id":"382c3795750aa664","repo":"kovidgoyal/kitty","slug":"computing-relative-path-w","errorCode":null,"errorMessage":"computing relative path: %w","messagePattern":"computing relative path: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"tools/utils/paths.go","lineNumber":374,"sourceCode":"\t// Make absolute and clean\n\tif base, err = filepath.Abs(base); err != nil {\n\t\treturn \"\", false, fmt.Errorf(\"abs base: %w\", err)\n\t}\n\tif target, err = filepath.Abs(target); err != nil {\n\t\treturn \"\", false, fmt.Errorf(\"abs target: %w\", err)\n\t}\n\n\t// On Windows the volume (drive letter) must match. If they don't, the path is not inside.\n\tif runtime.GOOS == \"windows\" {\n\t\tif !strings.EqualFold(filepath.VolumeName(base), filepath.VolumeName(target)) {\n\t\t\treturn \"\", false, nil\n\t\t}\n\t}\n\n\t// Get the relative path from base to target\n\trel, err = filepath.Rel(base, target)\n\tif err != nil {\n\t\treturn \"\", false, fmt.Errorf(\"computing relative path: %w\", err)\n\t}\n\n\t// If rel begins with \"..\" (or is \"..\"), then target is outside base.\n\t// Use os.PathSeparator to be portable.\n\tup := \"..\" + string(os.PathSeparator)\n\tif rel == \"..\" || strings.HasPrefix(rel, up) {\n\t\treturn \"\", false, nil\n\t}\n\n\t// If the returned rel is empty (shouldn't normally happen), normalize to \".\"\n\tif rel == \"\" {\n\t\trel = \".\"\n\t}\n\treturn rel, true, nil\n}\n","sourceCodeStart":356,"sourceCodeEnd":390,"githubUrl":"https://github.com/kovidgoyal/kitty/blob/6d5d0c440603ad9bdf6dcd599f73f6dde21acb44/tools/utils/paths.go#L356-L390","documentation":"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.","triggerScenarios":"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.","commonSituations":"Cross-drive comparisons on Windows, e.g. base under C:\\Users and target as a UNC \\\\server\\share path.","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."],"exampleFix":"// before\nrel, inside, err := utils.RelativeIfUnder(base, target, false)\n// after\nrel, inside, err := utils.RelativeIfUnder(base, target, false)\nif err != nil { // e.g. cross-volume on Windows\n    rel, inside, err = target, false, nil\n}","handlingStrategy":"fallback","validationCode":"if runtime.GOOS == \"windows\" && !strings.EqualFold(filepath.VolumeName(base), filepath.VolumeName(target)) {\n    // skip relative-path handling; different volumes\n}","typeGuard":null,"tryCatchPattern":"rel, inside, err := utils.RelativeIfUnder(base, target, false)\nif err != nil {\n    rel, inside = \"\", false // treat as outside base; use absolute target\n}","preventionTips":["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."],"tags":["go","windows","paths","cross-volume"],"backgroundTag":"path-resolution-failed","analyzedSha":"6d5d0c440603ad9bdf6dcd599f73f6dde21acb44","analyzedAt":"2026-08-27T14:20:20.142Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}