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

  1. Always pass an absolute base path (build it once at startup).
  2. If using ".", resolve it to an absolute path before the directory can disappear.
  3. Restart the tool from an existing directory if the CWD was deleted.
  4. 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

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


AI-assisted analysis of kovidgoyal/kitty@6d5d0c4406 (2026-08-27). Data as JSON: /api/errors/c0ab0056afe535c7. Report an issue: GitHub.