charmbracelet/crush · error
error starting background shell: %w
Error message
error starting background shell: %w
What it means
When params.RunInBackground is set, the bash tool starts the command via the background shell manager (bgManager.Start) on a detached context.Background so it survives the tool call. If Start returns an error — the process could not be spawned — the tool fails with 'error starting background shell' wrapping the underlying cause.
Source
Thrown at internal/agent/tools/bash.go:256
},
)
if err != nil {
return fantasy.ToolResponse{}, err
}
if !p {
return NewPermissionDeniedResponse(), nil
}
}
// If explicitly requested as background, start immediately with detached context
if params.RunInBackground {
startTime := time.Now()
bgManager := shell.GetBackgroundShellManager()
bgManager.Cleanup()
// Use background context so it continues after tool returns
bgShell, err := bgManager.Start(context.Background(), execWorkingDir, blockFuncs(), params.Command, params.Description)
if err != nil {
return fantasy.ToolResponse{}, fmt.Errorf("error starting background shell: %w", err)
}
// Wait a short time to detect fast failures (blocked commands, syntax errors, etc.)
time.Sleep(1 * time.Second)
stdout, stderr, done, execErr := bgShell.GetOutput()
if done {
// Command failed or completed very quickly
bgManager.Remove(bgShell.ID)
interrupted := shell.IsInterrupt(execErr)
exitCode := shell.ExitCode(execErr)
if exitCode == 0 && !interrupted && execErr != nil {
return fantasy.ToolResponse{}, fmt.Errorf("[Job %s] error executing command: %w", bgShell.ID, execErr)
}
stdout = formatOutput(stdout, stderr, execErr)
View on GitHub (pinned to 7944b8e522)
Solutions
- Verify the working directory passed in params.WorkingDir (or the tool's configured workingDir) exists and is readable/executable
- Confirm a shell is available on the host/container PATH and process spawning is permitted (ulimit, seccomp, sandbox policy)
- Check the wrapped cause (%w) for the OS-level reason (e.g. 'no such file or directory' vs 'fork: resource temporarily unavailable') and fix accordingly
- Restart the app if the background shell manager is in a wedged state after repeated failures
Example fix
// before Bash(command="ls", working_dir="/gone/path", run_in_background=true) // after Bash(command="ls", working_dir="/existing/project", run_in_background=true)
Defensive patterns
Strategy: validation
Validate before calling
if info, err := os.Stat(workingDir); err != nil || !info.IsDir() {
return fmt.Errorf("working dir %q is not usable: %w", workingDir, err)
}
if _, err := exec.LookPath("bash"); err != nil {
return fmt.Errorf("shell unavailable: %w", err)
} Try / catch
shell, err := bgManager.Start(ctx, dir, blockers, cmd, desc)
if err != nil {
var perr *exec.Error
if errors.As(err, &perr) { /* missing binary/PATH problem */ }
return fmt.Errorf("background shell unavailable: %w", err)
} Prevention
- Validate WorkingDir exists before passing it in Bash tool params
- Run in environments where the shell is on PATH and fork/exec is permitted
- Monitor ulimit/fd usage if spawning many background jobs
When it happens
Trigger: bgManager.Start fails while handling a RunInBackground=true bash call: the working directory (params.WorkingDir or the tool's workingDir) does not exist or is not accessible, the shell executable is missing, OS fork/exec limits are hit, or StartPersistent/Start fails internally.
Common situations: The model passes a WorkingDir that was deleted or never existed; running in a sandboxed container without a shell on PATH; hitting process/file-descriptor limits after many leaked background jobs.
Related errors
- [Job %s] error executing command: %w
- empty command
- session ID is required for executing shell command
- error starting shell: %w
- unsupported by the running server
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/817c14b7dc8e04e1.
Report an issue: GitHub.