kovidgoyal/kitty · warning
No files to copy specified
Error message
No files to copy specified
What it means
Returned by ParseCopyInstruction when the copy spec list resolves to zero local files. The kitten requires at least one file to transfer; an empty expansion (e.g. a glob matching nothing combined with no other sources) is rejected.
Source
Thrown at kittens/ssh/config.go:236
func ParseCopyInstruction(spec string) (ans []*CopyInstruction, err error) {
args, err := shlex.Split("copy " + spec)
if err != nil {
return nil, err
}
opts, args, err := parse_copy_args(args)
if err != nil {
return nil, err
}
locations := make([]string, 0, len(args))
for _, arg := range args {
locs, err := resolve_file_spec(arg, opts.Glob)
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)View on GitHub (pinned to 6d5d0c4406)
Solutions
- Verify the glob/pattern actually matches files: ls <pattern> in the same shell
- Guard in scripts: only invoke the kitten when the file list is non-empty
- Fix typos or stale paths in the copy specification
Example fix
# before kitty +kitten ssh --copy "logs/*.log" user@host # after ls logs/*.log >/dev/null 2>&1 && kitty +kitten ssh --copy "logs/*.log" user@host
Defensive patterns
Strategy: validation
Validate before calling
matches, _ := filepath.Glob(pattern)
if len(matches) == 0 {
// skip the copy call entirely
} Try / catch
if err := ParseCopyInstruction(opts); err != nil && strings.Contains(err.Error(), "No files to copy") {
// benign: nothing to transfer
return nil
} Prevention
- Expand globs in scripts and check length before invoking
- Treat empty expansion as a skip, not an error, in automation
When it happens
Trigger: Calling ParseCopyInstruction with a CopyFiles spec whose patterns all expand to empty sets — e.g. a wildcard like 'src/*.log' when the directory has no matching files, or an empty opts.Files list.
Common situations: Build scripts that pass a generated file list which ends up empty on clean checkouts; typos in glob patterns that silently match nothing; CI jobs where an artifact step was skipped.
Related errors
- Specifying a remote location with more than one file is not
- Unknown type_of_input: {type_of_input}
- Unknown keys in multicell_command:
- The value {x} is not a known choice
- The value {val} is not a valid choice for progress_bar
AI-assisted analysis of kovidgoyal/kitty@6d5d0c4406 (2026-08-27).
Data as JSON: /api/errors/dc8972adc278c1a6.
Report an issue: GitHub.