charmbracelet/crush · error

[Job %s] error executing command: %w

Error message

[Job %s] error executing command: %w

What it means

After starting a RunInBackground command, the tool waits 1 second to catch fast failures. If the process already finished (done) and returned a non-zero-ish execErr that is neither an interrupt nor a normal exit code, it is treated as a spawn/execution failure and reported as '[Job <id>] error executing command' wrapping execErr.

Source

Thrown at internal/agent/tools/bash.go:270

				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)

					metadata := BashResponseMetadata{
						StartTime:        startTime.UnixMilli(),
						EndTime:          time.Now().UnixMilli(),
						Output:           stdout,
						Description:      params.Description,
						Background:       params.RunInBackground,
						WorkingDirectory: bgShell.WorkingDir,
					}
					if stdout == "" {
						return fantasy.WithResponseMetadata(fantasy.NewTextResponse(BashNoOutput), metadata), nil
					}
					stdout += fmt.Sprintf("\n\n<cwd>%s</cwd>", normalizeWorkingDir(bgShell.WorkingDir))
					return fantasy.WithResponseMetadata(fantasy.NewTextResponse(stdout), metadata), nil
				}

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Read the wrapped cause and the job's stderr to see why the command died abnormally
  2. Remove or reformulate blocked commands (check the blocker list: curl|bash pipes, git push --force, yarn global add, go test -exec, etc.)
  3. Make the command executable/valid (chmod +x, fix interpreter shebang, correct syntax)
  4. If it is a legitimate command that exits non-zero, run it in the foreground to get the proper non-zero-exit response instead of this error path

Example fix

// before (blocked/invalid)
Bash(command="git push --force", run_in_background=true)
// after
Bash(command="git push --force-with-lease")
Defensive patterns

Strategy: type-guard

Validate before calling

// Prefer foreground for short-lived commands; background only for long-running ones
classify := func(dur time.Duration) bool { return dur > 30*time.Second }

Type guard

func isAbnormalExecFailure(err error) bool {
    return err != nil && !shell.IsInterrupt(err) && shell.ExitCode(err) == 0
}

Try / catch

if _, _, done, execErr := bgShell.GetOutput(); done && isAbnormalExecFailure(execErr) {
    var ee *exec.ExitError
    if errors.As(execErr, &ee) { /* inspect stderr */ }
    // fall back: rerun in foreground to surface a normal non-zero exit result
}

Prevention

When it happens

Trigger: A background command terminates within the 1-second probe window with an error whose ExitCode is 0 but err != nil and IsInterrupt is false — e.g. the shell failed to exec the command, the command was blocked by the blocker functions, or a shell-level setup error occurred rather than a normal non-zero exit.

Common situations: Command blocked by a block-list function (e.g. git push --force style blockers) causing an abnormal termination; shell syntax/setup failure that produces an error without a standard exit code; binary not executable so exec fails after start.

Related errors


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