charmbracelet/crush · error
could not run command: %w
Error message
could not run command: %w
What it means
After parsing succeeds, Run() constructs an interpreter via newRunner(opts.Cwd, opts.Env, ...). If interpreter construction fails (typically a bad working directory, invalid environment, or missing options), the failure is wrapped as "could not run command: %w". Unlike a parse error, the command may be valid but the runtime environment for it is not.
Source
Thrown at internal/shell/run.go:88
}
stdout := opts.Stdout
if stdout == nil {
stdout = io.Discard
}
stderr := opts.Stderr
if stderr == nil {
stderr = io.Discard
}
line, err := syntax.NewParser().Parse(strings.NewReader(opts.Command), "")
if err != nil {
return fmt.Errorf("could not parse command: %w", err)
}
runner, err := newRunner(opts.Cwd, opts.Env, opts.Stdin, stdout, stderr, opts.BlockFuncs)
if err != nil {
return fmt.Errorf("could not run command: %w", err)
}
return runner.Run(ctx, line)
}
// CaptureResult holds the combined output and exit code from a
// captured shell execution.
type CaptureResult struct {
Output string
ExitCode int
}
// PersistFunc is a callback that persists a shell command result.
// Used by RunAndPersist to decouple execution from storage.
type PersistFunc func(command, output string, exitCode int) error
// RunAndPersist executes a shell command via PTY and optionally
// persists the result through the provided callback. This unifiesView on GitHub (pinned to 7944b8e522)
Solutions
- Check that opts.Cwd exists and is a directory (os.Stat) before calling Run.
- Verify opts.Env entries are valid KEY=VALUE strings.
- Ensure stdout/stderr writers are non-nil and writable (Run defaults stderr to io.Discard, stdout must be provided).
- Inspect the wrapped %w error for the underlying cause (e.g. 'no such file or directory').
Example fix
// before
shell.Run(ctx, shell.RunOpts{Command: "ls", Cwd: "/tmp/does-not-exist"})
// after
if _, err := os.Stat(cwd); err != nil { return fmt.Errorf("bad cwd: %w", err) }
shell.Run(ctx, shell.RunOpts{Command: "ls", Cwd: cwd}) Defensive patterns
Strategy: validation
Validate before calling
if _, err := os.Stat(opts.Cwd); err != nil {
return fmt.Errorf("cwd unavailable: %w", err)
}
for _, e := range opts.Env {
if !strings.Contains(e, "=") { return errors.New("bad env entry: " + e) }
} Try / catch
if err := shell.Run(ctx, opts); err != nil {
if strings.HasPrefix(err.Error(), "could not run command") {
// log opts.Cwd/Env, retry after fixing setup
}
} Prevention
- Create/verify opts.Cwd with os.MkdirAll before Run.
- Build env with os.Environ() plus append rather than hand-assembled slices.
- Always pass non-nil stdout; remember stderr defaults to io.Discard.
- Re-validate directories in long-lived processes before each run.
When it happens
Trigger: Calling shell.Run with RunOpts whose Cwd does not exist or is not readable, an Env in an invalid format, or nil/invalid stdin/stdout/stderr writer configuration that newRunner rejects.
Common situations: Pointing Cwd at a deleted or renamed directory; passing an env slice built incorrectly; running in a container/CI where the configured working directory was not created before invoking Run.
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/c6ef249fb3e6ebd4.
Report an issue: GitHub.