charmbracelet/crush · error
docker MCP started but failed to persist configuration: %w
Error message
docker MCP started but failed to persist configuration: %w
What it means
This error is returned by EnableDockerMCP when the Docker MCP tool started successfully but PersistDockerMCPConfig failed to write the configuration to durable storage. The code deliberately rolls back (DisableSingle + RemoveDockerMCPInMemory) so no half-enabled state survives, and joins both the persist error and any rollback disable error into the message.
Source
Thrown at internal/backend/config.go:241
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
}
if err := mcptools.DisableSingle(ws.Cfg, config.DockerMCPName); err != nil {
return fmt.Errorf("failed to disable docker MCP: %w", err)
}
View on GitHub (pinned to 7944b8e522)
Solutions
- Check filesystem permissions and free space where the config is persisted.
- Inspect the wrapped persist error (errors.Join) to distinguish the write failure from rollback failure.
- Ensure only one process at a time modifies the workspace config (file locking or app-level serialization).
- After fixing, re-run EnableDockerMCP — the rollback should have left a clean state.
Defensive patterns
Strategy: validation
Validate before calling
info, err := os.Stat(configDir)
if err != nil || !info.IsDir() {
return fmt.Errorf("config dir missing: %s", configDir)
}
test := filepath.Join(configDir, ".write-test")
if err := os.WriteFile(test, nil, 0o644); err != nil {
return fmt.Errorf("config dir not writable: %w", err)
}
os.Remove(test) Type guard
func IsPersistErr(err error) bool {
return err != nil && strings.Contains(err.Error(), "failed to persist configuration")
} Try / catch
if err := backend.EnableDockerMCP(ctx, wsID, cfg); err != nil {
if strings.Contains(err.Error(), "failed to persist") {
// startup succeeded; state was rolled back — safe to retry after fixing FS
}
return err
} Prevention
- Ensure the config directory is writable by the process user at startup.
- Use file locking so only one process persists config at a time.
- Monitor disk space/quota in environments with small volumes.
- Treat persist failures as fatal-for-enable, never ignore and continue.
When it happens
Trigger: Calling EnableDockerMCP where InitializeSingle succeeds but ws.Cfg.PersistDockerMCPConfig(mcpConfig) returns an error — e.g. the config file is unwritable, the target directory is read-only, disk full, or a concurrent write corrupted the config store.
Common situations: Running in a container or sandbox with a read-only filesystem; insufficient permissions on ~/.config or the workspace .crush directory; disk quota exceeded; config file locked by another process.
Related errors
- failed to start docker MCP: %w
- failed to disable docker MCP: %w
- failed to enable docker MCP: %w
- failed to enable docker MCP: status code %d
- failed to disable docker MCP: %w
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/2033dbbcc4730204.
Report an issue: GitHub.