wavetermdev/waveterm · error
reading file %s: %w
Error message
reading file %s: %w
What it means
Wraps os.ReadFile(filePath) failure when a `wsh ai` argument is a regular file. os.Stat succeeded but the actual read failed — most commonly permission denied on the file itself, an I/O error, or the file being removed between Stat and Read. The wrapped error (*fs.PathError with EBADF/EACCES/EIO/EISDIR etc.) is preserved via %w.
Source
Thrown at cmd/wsh/cmd/wshcmd-ai.go:132
return fmt.Errorf("getting absolute path for %s: %w", filePath, err)
}
if fileInfo.IsDir() {
result, err := fileutil.ReadDir(filePath, 500)
if err != nil {
return fmt.Errorf("reading directory %s: %w", filePath, err)
}
jsonData, err := json.Marshal(result)
if err != nil {
return fmt.Errorf("marshaling directory listing for %s: %w", filePath, err)
}
data = jsonData
fileName = absPath
mimeType = "directory"
} else {
data, err = os.ReadFile(filePath)
if err != nil {
return fmt.Errorf("reading file %s: %w", filePath, err)
}
fileName = absPath
mimeType = detectMimeType(data)
}
}
isPDF := mimeType == "application/pdf"
isImage := strings.HasPrefix(mimeType, "image/")
isDirectory := mimeType == "directory"
if !isPDF && !isImage && !isDirectory {
mimeType = "text/plain"
if utilfn.ContainsBinaryData(data) {
return fmt.Errorf("file %s contains binary data and cannot be uploaded as text", fileName)
}
}
maxSize, sizeStr := getMaxFileSize(mimeType)View on GitHub (pinned to a4447c1563)
Solutions
- Check readability: `cat <file> >/dev/null`; fix with chmod/chown or use sudo to copy it somewhere readable first.
- Re-check the file still exists (`ls -l <file>`) — handle deletion races in scripts.
- If it's a fifo/device/symlink to one, attach a regular file (e.g. `cp` or dump contents to a temp file first).
- Investigate disk/mount health if the wrapped error is EIO.
Example fix
// before $ wsh ai /var/log/syslog // error: reading file /var/log/syslog: open ...: permission denied // after $ sudo cat /var/log/syslog | wsh ai -
Defensive patterns
Strategy: validation
Validate before calling
for f in "$@"; do
if [ -f "$f" ] && ! [ -r "$f" ]; then
echo "file not readable: $f" >&2; exit 1
fi
done Try / catch
if err := runAI(args); err != nil {
var perr *fs.PathError
if errors.As(err, &perr) {
switch {
case errors.Is(perr.Err, syscall.EACCES):
return fmt.Errorf("no read permission on %q; chmod/copy first", perr.Path)
case errors.Is(perr.Err, syscall.EIO):
return fmt.Errorf("I/O error reading %q; check disk/mount health", perr.Path)
}
}
return err
} Prevention
- Probe readability with `cat <file> >/dev/null` before attaching root-owned or system files.
- Avoid attaching fifos, device nodes, or files on unstable mounts.
- In scripts, re-verify existence just before the call to avoid Stat/ReadFile races.
When it happens
Trigger: `wsh ai <file>` where the file exists but is not readable by the current user (Stat can succeed via parent dir +x without file r), the file is a special device/fifo that fails on read, it was deleted between Stat and ReadFile, or hardware/IO errors occur.
Common situations: Reading logs owned by root as a normal user; attaching files on a dying disk or full/failed mount; scripts racing with file deletion; attaching /dev files by mistake.
Related errors
- accessing file %s: %w
- reading directory %s: %w
- failed to read directory: %w
- getting absolute path for %s: %w
- error creating listener at %v: %v
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/ee7b27b9171bb191.
Report an issue: GitHub.