kovidgoyal/kitty · error
abs base: %w
Error message
abs base: %w
What it means
RelativeIfUnder makes the base path absolute via filepath.Abs before comparing. Abs only fails when filepath.Abs itself errors — in practice when the current working directory cannot be determined (os.Getwd fails), since Abs of a relative base needs the CWD. This error wraps that failure.
Source
Thrown at tools/utils/paths.go:358
//
// Notes:
// - This uses filepath.Rel and then checks for leading ".." components to determine
// whether the returned relative path escapes the base directory.
// - On Windows behaviour is consistent with filepath semantics.
func RelativeIfUnder(base, target string, resolveSymlinks bool) (rel string, inside bool, err error) {
// Optionally resolve symlinks first
if resolveSymlinks {
if base, err = filepath.EvalSymlinks(base); err != nil {
return "", false, fmt.Errorf("resolving base symlinks: %w", err)
}
if target, err = filepath.EvalSymlinks(target); err != nil {
return "", false, fmt.Errorf("resolving target symlinks: %w", err)
}
}
// 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)
}
View on GitHub (pinned to 6d5d0c4406)
Solutions
- Always pass an absolute base path (build it once at startup).
- If using ".", resolve it to an absolute path before the directory can disappear.
- Restart the tool from an existing directory if the CWD was deleted.
- Check errors from os.Getwd at startup and fail fast with a clear message.
Example fix
// before
rel, inside, err := utils.RelativeIfUnder(".", target, false)
// after
base, _ := filepath.Abs(".") // captured at startup
rel, inside, err := utils.RelativeIfUnder(base, target, false) Defensive patterns
Strategy: validation
Validate before calling
if !filepath.IsAbs(base) {
if abs, err := filepath.Abs(base); err == nil {
base = abs
} else {
return err // CWD unavailable
}
} Type guard
func cwdAvailable() bool {
wd, err := os.Getwd()
return err == nil && wd != ""
} Try / catch
rel, inside, err := utils.RelativeIfUnder(base, target, false)
if err != nil {
if _, gerr := os.Getwd(); gerr != nil {
return fmt.Errorf("working directory lost; pass absolute paths: %w", err)
}
} Prevention
- Normalize base to an absolute path at process start.
- Check os.Getwd at startup and fail fast.
- Never rely on a CWD surviving long-lived processes.
When it happens
Trigger: Calling with a relative base path from a process whose CWD has been deleted (e.g. the directory the tool was launched from was rm -rf'd), or in environments where getwd is disallowed.
Common situations: Long-running daemons/sessions whose startup directory was removed; shell in a deleted directory then invoking the tool with a relative base like ".".
Related errors
- abs target: %w
- resolving base symlinks: %w
- resolving target symlinks: %w
- Failed to convert image data output file: %s to absolute pat
- Failed to open %s for reading with error: %w
AI-assisted analysis of kovidgoyal/kitty@6d5d0c4406 (2026-08-27).
Data as JSON: /api/errors/c0ab0056afe535c7.
Report an issue: GitHub.