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
- Check os.Stat on the shell's current working directory and SetWorkingDir to a valid directory if missing.
- Inspect the wrapped %w error for the concrete cause from newInterp.
- Ensure stdout/stderr writers passed to the Shell are non-nil and usable.
- 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
- Periodically verify the shell's cwd still exists in long-running sessions.
- Point the shell at stable directories, not ephemeral temp dirs that get cleaned.
- Ensure stream writers passed to the Shell remain valid for its lifetime.
- Recreate the Shell if configuration state becomes invalid.
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
- could not run command: %w
- empty shebang
- env: missing program name
- env -S requires a program
- empty command
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/d08e96db985c2749.
Report an issue: GitHub.