kovidgoyal/kitty · error

abs target: %w

Error message

abs target: %w

What it means

RelativeIfUnder makes the target absolute with filepath.Abs after symlink resolution. Like the base variant, it only fails when os.Getwd fails (deleted/unreadable working directory) while resolving a relative target. The wrapped error distinguishes the exact cause.

Source

Thrown at tools/utils/paths.go:361

//     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)
	}

	// If rel begins with ".." (or is ".."), then target is outside base.
	// Use os.PathSeparator to be portable.
	up := ".." + string(os.PathSeparator)

View on GitHub (pinned to 6d5d0c4406)

Solutions

  1. Convert targets to absolute paths before calling (filepath.Abs at argument-parse time).
  2. Re-run from a valid working directory.
  3. Avoid holding relative paths across long-running operations; normalize early.
  4. Handle the error and prompt the user to re-supply the path.

Example fix

// before
rel, inside, err := utils.RelativeIfUnder(base, relTarget, false)
// after
absTarget, _ := filepath.Abs(relTarget)
rel, inside, err := utils.RelativeIfUnder(base, absTarget, false)
Defensive patterns

Strategy: validation

Validate before calling

target, _ = filepath.Abs(target) // resolve while CWD is still valid
rel, inside, err := utils.RelativeIfUnder(base, target, false)

Try / catch

rel, inside, err := utils.RelativeIfUnder(base, target, false)
if err != nil {
    if _, gerr := os.Getwd(); gerr != nil {
        return fmt.Errorf("CWD unavailable for relative target %q: %w", target, err)
    }
}

Prevention

When it happens

Trigger: Relative target path plus a process CWD that has been deleted or is unreadable; sandboxed runtimes blocking getwd.

Common situations: Tool invoked with relative file arguments from a directory that later disappears; containers where WORKDIR was removed at runtime.

Related errors


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