kovidgoyal/kitty · error
Failed to resolve symlinks in %#v with error: %w
Error message
Failed to resolve symlinks in %#v with error: %w
What it means
Raised when filepath.EvalSymlinks fails on a copy source while the symlink strategy is not 'preserve'. The kitten tries to canonicalize the path (resolve symlink chains) before archiving, and the underlying OS call returned an error such as ENOENT or ELOOP.
Source
Thrown at kittens/ssh/config.go:248
if err != nil {
return nil, err
}
locations = append(locations, locs...)
}
if len(locations) == 0 {
return nil, fmt.Errorf("No files to copy specified")
}
if len(locations) > 1 && opts.Dest != "" {
return nil, fmt.Errorf("Specifying a remote location with more than one file is not supported")
}
home := paths_ctx.HomePath()
ans = make([]*CopyInstruction, 0, len(locations))
for _, loc := range locations {
ci := CopyInstruction{local_path: loc, exclude_patterns: opts.Exclude}
if opts.SymlinkStrategy != "preserve" {
ci.local_path, err = filepath.EvalSymlinks(loc)
if err != nil {
return nil, fmt.Errorf("Failed to resolve symlinks in %#v with error: %w", loc, err)
}
}
if opts.SymlinkStrategy == "resolve" {
ci.arcname = get_arcname(ci.local_path, opts.Dest, home)
} else {
ci.arcname = get_arcname(loc, opts.Dest, home)
}
ans = append(ans, &ci)
}
return
}
type file_unique_id struct {
dev, inode uint64
}
func excluded(pattern, path string) bool {
if !strings.ContainsRune(pattern, '/') {View on GitHub (pinned to 6d5d0c4406)
Solutions
- Inspect the path: readlink -f <path> to see where it fails
- Remove or fix the dangling/looping symlink
- Set symlink strategy to 'preserve' if you want such symlinks passed through unchanged
Example fix
# before (default resolves symlinks) kitty +kitten ssh --copy "~/.some/link" user@host # after kitty +kitten ssh --symlink-strategy preserve --copy "~/.some/link" user@host
Defensive patterns
Strategy: validation
Validate before calling
if _, err := filepath.EvalSymlinks(path); err != nil {
// broken link: skip or use symlink_strategy=preserve
} Try / catch
if _, err := os.Readlink(path); err == nil {
if _, terr := filepath.EvalSymlinks(path); terr != nil {
// pass through with preserve strategy instead
}
} Prevention
- Prune dangling symlinks from copy trees (find . -xtype l)
- Use symlink strategy 'preserve' when the tree intentionally contains links
When it happens
Trigger: ParseCopyInstruction with symlink strategy 'resolve' (default) on a path that is a dangling symlink, a symlink loop, or a path whose target was removed between globbing and resolution.
Common situations: Copying from directories containing broken editor backup links or /tmp symlinks to deleted files; race with a cleanup job deleting the target; symlink loops in dotfiles repos.
Related errors
- Cannot read from: %s with error: %w
- resolving base symlinks: %w
- resolving target symlinks: %w
- %s is not a directory while resolving symlinks in %s
- Unknown link target type
AI-assisted analysis of kovidgoyal/kitty@6d5d0c4406 (2026-08-27).
Data as JSON: /api/errors/0799ac8969a4d9dd.
Report an issue: GitHub.