{"record":{"id":"c6ef249fb3e6ebd4","repo":"charmbracelet/crush","slug":"could-not-run-command-w","errorCode":null,"errorMessage":"could not run command: %w","messagePattern":"could not run command: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/shell/run.go","lineNumber":88,"sourceCode":"\t}\n\n\tstdout := opts.Stdout\n\tif stdout == nil {\n\t\tstdout = io.Discard\n\t}\n\tstderr := opts.Stderr\n\tif stderr == nil {\n\t\tstderr = io.Discard\n\t}\n\n\tline, err := syntax.NewParser().Parse(strings.NewReader(opts.Command), \"\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"could not parse command: %w\", err)\n\t}\n\n\trunner, err := newRunner(opts.Cwd, opts.Env, opts.Stdin, stdout, stderr, opts.BlockFuncs)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"could not run command: %w\", err)\n\t}\n\n\treturn runner.Run(ctx, line)\n}\n\n// CaptureResult holds the combined output and exit code from a\n// captured shell execution.\ntype CaptureResult struct {\n\tOutput   string\n\tExitCode int\n}\n\n// PersistFunc is a callback that persists a shell command result.\n// Used by RunAndPersist to decouple execution from storage.\ntype PersistFunc func(command, output string, exitCode int) error\n\n// RunAndPersist executes a shell command via PTY and optionally\n// persists the result through the provided callback. This unifies","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/shell/run.go#L70-L106","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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')."],"exampleFix":"// before\nshell.Run(ctx, shell.RunOpts{Command: \"ls\", Cwd: \"/tmp/does-not-exist\"})\n// after\nif _, err := os.Stat(cwd); err != nil { return fmt.Errorf(\"bad cwd: %w\", err) }\nshell.Run(ctx, shell.RunOpts{Command: \"ls\", Cwd: cwd})","handlingStrategy":"validation","validationCode":"if _, err := os.Stat(opts.Cwd); err != nil {\n\treturn fmt.Errorf(\"cwd unavailable: %w\", err)\n}\nfor _, e := range opts.Env {\n\tif !strings.Contains(e, \"=\") { return errors.New(\"bad env entry: \" + e) }\n}","typeGuard":null,"tryCatchPattern":"if err := shell.Run(ctx, opts); err != nil {\n\tif strings.HasPrefix(err.Error(), \"could not run command\") {\n\t\t// log opts.Cwd/Env, retry after fixing setup\n\t}\n}","preventionTips":["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."],"tags":["shell","runner-setup","environment"],"backgroundTag":"shell-execution-setup-failed","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}