kovidgoyal/kitty · error

Cannot read from: %s with error: %w

Error message

Cannot read from: %s with error: %w

What it means

Thrown by resolve_file_spec when unix.Access(path, R_OK) fails for a local file/directory spec in the ssh kitten's copy syntax. It means the path exists (or at least the error is not ENOENT) but the process cannot read it, typically EACCES/EPERM. The offending spec string is included in the message.

Source

Thrown at kittens/ssh/config.go:194

	if !filepath.IsAbs(ans) {
		ans = paths_ctx.AbspathFromHome(ans)
	}
	if is_glob {
		files, err := doublestar.FilepathGlob(ans)
		if err != nil {
			return nil, fmt.Errorf("%s is not a valid glob pattern with error: %w", spec, err)
		}
		if len(files) == 0 {
			return nil, fmt.Errorf("%s matches no files", spec)
		}
		return files, nil
	}
	err := unix.Access(ans, unix.R_OK)
	if err != nil {
		if errors.Is(err, os.ErrNotExist) {
			return nil, fmt.Errorf("%s does not exist", spec)
		}
		return nil, fmt.Errorf("Cannot read from: %s with error: %w", spec, err)
	}
	return []string{ans}, nil
}

func get_arcname(loc, dest, home string) (arcname string) {
	if dest != "" {
		arcname = dest
	} else {
		arcname = filepath.Clean(loc)
		if strings.HasPrefix(arcname, home) {
			ra, err := filepath.Rel(home, arcname)
			if err == nil {
				arcname = ra
			}
		}
	}
	prefix := "home/"
	if strings.HasPrefix(arcname, "/") {

View on GitHub (pinned to 6d5d0c4406)

Solutions

  1. Check the path's permissions: ls -l <spec> and chmod u+r (or chown) it
  2. Verify every parent directory grants execute (x) permission to your user: namei -l <spec>
  3. Run the kitten as the user who owns the file, or copy the file to a readable location first
  4. If the path should not exist at all, remove it — a different error (does not exist) only fires on ENOENT

Example fix

# before
kitty +kitten ssh --copy myuser@host:/data/secret.conf
# after (make it readable)
chmod u+r /data/secret.conf
kitty +kitten ssh --copy myuser@host:/data/secret.conf
Defensive patterns

Strategy: validation

Validate before calling

if err := unix.Access(path, unix.R_OK); err != nil {
    log.Printf("cannot read %s: %v", path, err)
    // fix perms or skip
}

Try / catch

if _, err := kitten.ParseCopyInstruction(spec); err != nil {
    if strings.Contains(err.Error(), "Cannot read from") { /* fix perms, skip file */ }
}

Prevention

When it happens

Trigger: ParseCopyInstruction with --copy or COPY: directives referencing a path that exists but is not readable by the current user (wrong ownership, missing read bit, or a parent directory without +x). Also paths with permission-restricted parents on some filesystems.

Common situations: Running kitty ssh kitten as a different user via sudo/su; files created by root in the home directory; hardened umask; NFS mounts with root_squash; passing /proc or /sys pseudo-files.

Related errors


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