charmbracelet/crush · error

failed to start docker MCP: %w

Error message

failed to start docker MCP: %w

What it means

EnableDockerMCP starts the Docker MCP tool in a workspace and rolls it back (DisableSingle + RemoveDockerMCPInMemory) if startup fails. This error wraps both the original startup error and any rollback disable error via errors.Join, so the message may contain multiple causes. It means the Docker MCP server could not be initialized and the workspace config was reverted to its pre-enable state.

Source

Thrown at internal/backend/config.go:235

}

// EnableDockerMCP validates Docker MCP availability, stages the
// configuration, starts the MCP client, and persists the config.
func (b *Backend) EnableDockerMCP(ctx context.Context, workspaceID string) error {
	ws, err := b.GetWorkspace(workspaceID)
	if err != nil {
		return err
	}

	mcpConfig, err := ws.Cfg.PrepareDockerMCPConfig()
	if err != nil {
		return err
	}

	if err := mcptools.InitializeSingle(ctx, config.DockerMCPName, ws.Cfg); err != nil {
		disableErr := mcptools.DisableSingle(ws.Cfg, config.DockerMCPName)
		ws.Cfg.RemoveDockerMCPInMemory()
		return fmt.Errorf("failed to start docker MCP: %w", errors.Join(err, disableErr))
	}

	if err := ws.Cfg.PersistDockerMCPConfig(mcpConfig); err != nil {
		disableErr := mcptools.DisableSingle(ws.Cfg, config.DockerMCPName)
		ws.Cfg.RemoveDockerMCPInMemory()
		return fmt.Errorf("docker MCP started but failed to persist configuration: %w", errors.Join(err, disableErr))
	}

	publishConfigChanged(ws)
	return nil
}

// DisableDockerMCP closes the Docker MCP client, removes the
// configuration, and persists the change.
func (b *Backend) DisableDockerMCP(workspaceID string) error {
	ws, err := b.GetWorkspace(workspaceID)
	if err != nil {
		return err

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Verify Docker is installed and the daemon is running (docker info) before enabling.
  2. Check the joined inner errors: the first is the InitializeSingle failure, the second (if any) the rollback failure — fix the root cause first.
  3. Validate the mcpConfig command/args/env values; test the command manually in a shell.
  4. Retry EnableDockerMCP after correcting config; confirm no partial state remains via RemoveDockerMCPInMemory semantics or a fresh workspace read.

Example fix

// before
if err := mcptools.InitializeSingle(ctx, config.DockerMCPName, ws.Cfg); err != nil { /* opaque failure */ }
// after
// log/inspect the joined error to separate startup vs rollback causes, and pre-validate docker:
if _, err := exec.LookPath("docker"); err != nil {
    return fmt.Errorf("docker binary not found: %w", err)
}
if err := mcptools.InitializeSingle(ctx, config.DockerMCPName, ws.Cfg); err != nil { ... }
Defensive patterns

Strategy: try-catch

Validate before calling

if _, err := exec.LookPath("docker"); err != nil {
    return fmt.Errorf("docker binary not found: %w", err)
}
if err := ws.Cfg.ValidateMCPConfig(mcpConfig); err != nil {
    return fmt.Errorf("invalid mcp config: %w", err)
}

Type guard

func IsDockerMCPStartupErr(err error) bool {
    return err != nil && strings.Contains(err.Error(), "failed to start docker MCP")
}

Try / catch

if err := backend.EnableDockerMCP(ctx, wsID, cfg); err != nil {
    var joined interface{ Unwrap() []error }
    if errors.As(err, &joined) {
        for _, e := range joined.Unwrap() { log.Printf("cause: %v", e) }
    }
    return fmt.Errorf("docker MCP enable aborted: %w", err)
}

Prevention

When it happens

Trigger: Calling EnableDockerMCP(workspaceID, mcpConfig) when mcptools.InitializeSingle fails — e.g. the docker MCP binary/command defined in mcpConfig is missing, fails to launch, the docker daemon is unavailable, or the MCP handshake times out; the wrapped disableErr additionally appears if DisableSingle itself also fails during rollback.

Common situations: Docker not running or not installed on the host; an invalid MCP command/args in the submitted config; permission denied executing the MCP binary; stale workspace config referencing a removed tool; concurrent config edits causing the rollback disable to also error.

Related errors


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