wavetermdev/waveterm · error

reading directory %s: %w

Error message

reading directory %s: %w

What it means

Wraps fileutil.ReadDir(filePath, 500) failure when a `wsh ai` argument is a directory. The command builds a JSON directory listing (max 500 entries) instead of reading file contents. This error means the directory listing failed — permission denied, the path disappeared between Stat and ReadDir, or it is not actually a readable directory.

Source

Thrown at cmd/wsh/cmd/wshcmd-ai.go:120

			if err != nil {
				return fmt.Errorf("reading from stdin: %w", err)
			}
			fileName = "stdin"
			mimeType = "text/plain"
		} else {
			fileInfo, err := os.Stat(filePath)
			if err != nil {
				return fmt.Errorf("accessing file %s: %w", filePath, err)
			}
			absPath, err := filepath.Abs(filePath)
			if err != nil {
				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)
			}
		}

View on GitHub (pinned to a4447c1563)

Solutions

  1. Check directory readability: `ls <dir>`; fix permissions with chmod/chown if needed.
  2. Verify the directory still exists right before running (guards against races in scripts).
  3. Attach specific files from the directory instead of the directory itself.
  4. If the listing would exceed 500 entries, attach a narrower subdirectory or a filtered file list.

Example fix

// before
$ wsh ai /var/log/private
// after
$ sudo chmod o+rx /var/log/private  # or attach readable files instead
$ wsh ai /var/log/private/app.log
Defensive patterns

Strategy: validation

Validate before calling

if [ -d "$dir" ] && ! [ -r "$dir" ] && ! [ -x "$dir" ]; then
  echo "directory not readable: $dir" >&2
  exit 1
fi
entry_count=$(ls -1 "$dir" | wc -l)
[ "$entry_count" -le 500 ] || echo "warning: $dir has $entry_count entries; listing truncated at 500"

Try / catch

if err := runAI(args); err != nil {
    var perr *fs.PathError
    if errors.As(err, &perr) && errors.Is(perr.Err, syscall.EACCES) {
        return fmt.Errorf("cannot read directory %q: fix permissions or attach individual files", perr.Path)
    }
    return err
}

Prevention

When it happens

Trigger: `wsh ai <dir>` where the directory is unreadable (no r permission), the directory was removed between os.Stat and ReadDir (race), or a special filesystem returns errors on readdir.

Common situations: Attaching /root or another protected directory as a normal user; attaching a directory on a failing mount/NFS; scripts where the directory is deleted concurrently.

Related errors


AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01). Data as JSON: /api/errors/ccb6052eca7e8494. Report an issue: GitHub.