kovidgoyal/kitty · error · ValueError

Not an appropriate file type

Error message

Not an appropriate file type

What it means

make_ftc inspects an lstat result and classifies the path as symlink, directory, or regular file. Anything else (socket, FIFO, device file, etc.) cannot be transmitted and raises ValueError('Not an appropriate file type').

Source

Thrown at kitty/file_transmission.py:89

def iter_file_metadata(file_specs: Iterable[tuple[str, str]]) -> Iterator[Union['FileTransmissionCommand', 'TransmissionError']]:
    file_map: DefaultDict[tuple[int, int], list[FileTransmissionCommand]] = defaultdict(list)
    counter = count()

    def skey(sr: os.stat_result) -> tuple[int, int]:
        return sr.st_dev, sr.st_ino

    def make_ftc(path: str, spec_id: str, sr: os.stat_result | None = None, parent: str = '') -> FileTransmissionCommand:
        if sr is None:
            sr = os.stat(path, follow_symlinks=False)
        if stat.S_ISLNK(sr.st_mode):
            ftype = FileType.symlink
        elif stat.S_ISDIR(sr.st_mode):
            ftype = FileType.directory
        elif stat.S_ISREG(sr.st_mode):
            ftype = FileType.regular
        else:
            raise ValueError('Not an appropriate file type')
        ans = FileTransmissionCommand(
            action=Action.file,
            file_id=spec_id,
            mtime=sr.st_mtime_ns,
            permissions=stat.S_IMODE(sr.st_mode),
            name=path,
            status=str(next(counter)),
            size=sr.st_size,
            ftype=ftype,
            parent=parent,
        )
        file_map[skey(sr)].append(ans)
        return ans

    def add_dir(ftc: FileTransmissionCommand) -> None:
        try:
            lr = os.listdir(ftc.name)
        except OSError:

View on GitHub (pinned to 6d5d0c4406)

Solutions

  1. Filter non-regular files before transmission (stat.S_ISREG / ISLNK / ISDIR check).
  2. Exclude device/socket directories like /dev, /proc, /run from the transfer set.
  3. Retry after removing the transient socket/fifo if it was short-lived.

Example fix

# before
for p in paths:
    make_ftc(p)
# after
for p in paths:
    m = os.lstat(p).st_mode
    if stat.S_ISREG(m) or stat.S_ISLNK(m) or stat.S_ISDIR(m):
        make_ftc(p)
Defensive patterns

Strategy: type-guard

Validate before calling

import stat, os
m = os.lstat(path).st_mode
assert stat.S_ISREG(m) or stat.S_ISDIR(m) or stat.S_ISLNK(m), path

Type guard

def is_transmittable(path: str) -> bool:
    import stat, os
    m = os.lstat(path).st_mode
    return stat.S_ISREG(m) or stat.S_ISDIR(m) or stat.S_ISLNK(m)

Try / catch

try:
    make_ftc(path)
except ValueError:
    logging.warning('skipping unsupported file type: %s', path)

Prevention

When it happens

Trigger: Calling kitty's file-transmission metadata builder on a path whose st_mode is not S_ISLNK/S_ISDIR/S_ISREG — e.g. /dev/null, a unix socket, or a named pipe discovered during add_dir/iter_file_metadata traversal.

Common situations: Globbing a directory tree that contains sockets or FIFOs (e.g. forwarding into a runtime dir); explicitly passing /dev/... paths; picking up transient files created by other processes during traversal.

Related errors


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