wavetermdev/waveterm · error

%s is not a directory

Error message

%s is not a directory

What it means

The directory-walk helper in pkg/suggestion verifies with f.Stat() that the path it was asked to list is actually a directory before ReadDir. If the path exists but is a regular file (or other non-dir), it returns this error instead of proceeding.

Source

Thrown at pkg/suggestion/filewalk.go:162

				}
			}
		}()
		return ch, nil
	}

	// Use singleflight to ensure only one listing operation occurs per key.
	value, err, _ := group.Do(key, func() (interface{}, error) {
		f, err := os.Open(dir)
		if err != nil {
			return nil, err
		}
		defer f.Close()
		fi, err := f.Stat()
		if err != nil {
			return nil, err
		}
		if !fi.IsDir() {
			return nil, fmt.Errorf("%s is not a directory", dir)
		}
		entries, err := f.ReadDir(maxFiles)
		if err != nil {
			return nil, err
		}
		var results []DirEntryResult
		for _, entry := range entries {
			results = append(results, DirEntryResult{Entry: entry})
		}
		// Add parent directory (“..”) entry if not at the filesystem root.
		if filepath.Dir(dir) != dir {
			mockDir := &MockDirEntry{
				NameStr:  "..",
				IsDirVal: true,
				FileMode: fs.ModeDir | 0755,
			}
			results = append(results, DirEntryResult{Entry: mockDir})
		}

View on GitHub (pinned to a4447c1563)

Solutions

  1. Check os.Stat(dir).IsDir() before invoking the directory list call
  2. If the resolved path is a file, treat it as the matched entry rather than a directory to walk
  3. Correct the baseDir/query resolution (resolveFileQuery) so it yields a directory

Example fix

// before
results, err := ListDir(candidatePath, maxFiles)
// after
if fi, statErr := os.Stat(candidatePath); statErr != nil || !fi.IsDir() {
    return nil
}
results, err := ListDir(candidatePath, maxFiles)
Defensive patterns

Strategy: validation

Validate before calling

fi, err := os.Stat(dir)
if err != nil { return err }
if !fi.IsDir() {
    return fmt.Errorf("%s is not a directory", dir)
}

Type guard

func isDir(path string) bool { fi, err := os.Stat(path); return err == nil && fi.IsDir() }

Try / catch

results, err := ListDir(dir, maxFiles)
if err != nil && strings.HasSuffix(err.Error(), "is not a directory") {
    return nil // treat as no suggestions for a file path
}

Prevention

When it happens

Trigger: Calling the internal listDirectory function of filewalk with a path that exists but is a file, e.g. a query resolving to /home/user/file.txt instead of a directory.

Common situations: File suggestion queries that autocomplete to a full file path, stale cached baseDir pointing at a file that replaced a directory, symlink resolution producing a file path.

Related errors


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