charmbracelet/crush · error

directory does not exist: %w

Error message

directory does not exist: %w

What it means

Shell.SetWorkingDir in internal/shell/shell.go verifies the target directory with os.Stat before switching the shell's working directory. If Stat fails (missing path, permission problem, or path is a file), the raw error is wrapped as "directory does not exist: %w" and the cwd is left unchanged. The shell state is protected under a mutex, so the error is atomic.

Source

Thrown at internal/shell/shell.go:148

	return s.execStream(ctx, command, stdout, stderr)
}

// GetWorkingDir returns the current working directory
func (s *Shell) GetWorkingDir() string {
	s.mu.Lock()
	defer s.mu.Unlock()
	return s.cwd
}

// SetWorkingDir sets the working directory
func (s *Shell) SetWorkingDir(dir string) error {
	s.mu.Lock()
	defer s.mu.Unlock()

	// Verify the directory exists
	if _, err := os.Stat(dir); err != nil {
		return fmt.Errorf("directory does not exist: %w", err)
	}

	s.cwd = dir
	return nil
}

// GetEnv returns a copy of the environment variables
func (s *Shell) GetEnv() []string {
	s.mu.Lock()
	defer s.mu.Unlock()

	env := make([]string, len(s.env))
	copy(env, s.env)
	return env
}

// SetEnv sets an environment variable
func (s *Shell) SetEnv(key, value string) {

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Create the directory first (os.MkdirAll) before calling SetWorkingDir.
  2. Verify the path is a directory, not a file, and fix the caller.
  3. Check permissions on the path and its parents.
  4. Re-check the stored path for staleness (deleted temp/worktree dirs) and resolve to an existing directory.

Example fix

// before
shell.SetWorkingDir("/tmp/build-123") // may not exist
// after
os.MkdirAll("/tmp/build-123", 0o755)
shell.SetWorkingDir("/tmp/build-123")
Defensive patterns

Strategy: validation

Validate before calling

func dirExists(p string) bool {
	info, err := os.Stat(p)
	return err == nil && info.IsDir()
}
if !dirExists(dir) { os.MkdirAll(dir, 0o755) }
err := sh.SetWorkingDir(dir)

Try / catch

if err := sh.SetWorkingDir(dir); err != nil {
	var pe *fs.PathError
	if errors.As(err, &pe) && errors.Is(pe.Err, fs.ErrNotExist) {
		os.MkdirAll(dir, 0o755)
		err = sh.SetWorkingDir(dir)
	}
}

Prevention

When it happens

Trigger: Calling SetWorkingDir("/path/that/does/not/exist"), calling it with a file path instead of a directory, or with a path the process lacks search permission on. Any os.Stat error (including permission) yields this message.

Common situations: Restoring a session whose previous cwd was deleted; pointing the shell at a worktree or temp dir that was cleaned up; typo in path; using a path inside a container that was never mounted.

Related errors


AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29). Data as JSON: /api/errors/63b413efe98671c1. Report an issue: GitHub.