charmbracelet/crush · error

could not run command: %w

Error message

could not run command: %w

What it means

In execCommon, after successful parsing the shell builds an interpreter with s.newInterp(nil, stdout, stderr). If construction fails, the error is wrapped as "could not run command: %w" and no command runs. This reflects an environment/configuration problem (working directory, env, streams) rather than shell syntax.

Source

Thrown at internal/shell/shell.go:278

	var runner *interp.Runner
	defer func() {
		if r := recover(); r != nil {
			err = fmt.Errorf("command execution panic: %v", r)
		}
		if runner != nil {
			s.updateShellFromRunner(runner)
		}
		s.logger.InfoPersist("command finished", "command", command, "err", err)
	}()

	line, err := syntax.NewParser().Parse(strings.NewReader(command), "")
	if err != nil {
		return fmt.Errorf("could not parse command: %w", err)
	}

	runner, err = s.newInterp(nil, stdout, stderr)
	if err != nil {
		return fmt.Errorf("could not run command: %w", err)
	}

	err = runner.Run(ctx, line)
	return err
}

// exec executes commands using a cross-platform shell interpreter.
func (s *Shell) exec(ctx context.Context, command string) (string, string, error) {
	var stdout, stderr bytes.Buffer
	err := s.execCommon(ctx, command, &stdout, &stderr)
	return stdout.String(), stderr.String(), err
}

// execStream executes commands using POSIX shell emulation with streaming output
func (s *Shell) execStream(ctx context.Context, command string, stdout, stderr io.Writer) error {
	return s.execCommon(ctx, command, stdout, stderr)
}

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Check os.Stat on the shell's current working directory and SetWorkingDir to a valid directory if missing.
  2. Inspect the wrapped %w error for the concrete cause from newInterp.
  3. Ensure stdout/stderr writers passed to the Shell are non-nil and usable.
  4. Recreate the Shell instance if its environment state has become invalid.

Example fix

// before
sh.Exec(ctx, cmd) // fails after cwd deleted
// after
if _, err := os.Stat(sh.WorkingDir()); err != nil {
	sh.SetWorkingDir("/tmp")
}
sh.Exec(ctx, cmd)
Defensive patterns

Strategy: validation

Validate before calling

if _, err := os.Stat(sh.WorkingDir()); err != nil {
	_ = sh.SetWorkingDir("/tmp") // or recreate
}

Try / catch

err := sh.Exec(ctx, cmd)
if err != nil && strings.HasPrefix(err.Error(), "could not run command") {
	// verify/repair cwd+env, then retry once
}

Prevention

When it happens

Trigger: Calling Shell.exec/execStream while the shell's cwd (set via SetWorkingDir) no longer exists, the configured environment is invalid, or stream writers supplied to the Shell are unsuitable, causing newInterp to fail.

Common situations: Long-running sessions where the original working directory was deleted between commands; CI containers removing temp dirs; misconfigured env plumbing through the Shell.

Related errors


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