{"record":{"id":"2033dbbcc4730204","repo":"charmbracelet/crush","slug":"docker-mcp-started-but-failed-to-persist-configura","errorCode":null,"errorMessage":"docker MCP started but failed to persist configuration: %w","messagePattern":"docker MCP started but failed to persist configuration: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/backend/config.go","lineNumber":241,"sourceCode":"\tif err != nil {\n\t\treturn err\n\t}\n\n\tmcpConfig, err := ws.Cfg.PrepareDockerMCPConfig()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif err := mcptools.InitializeSingle(ctx, config.DockerMCPName, ws.Cfg); err != nil {\n\t\tdisableErr := mcptools.DisableSingle(ws.Cfg, config.DockerMCPName)\n\t\tws.Cfg.RemoveDockerMCPInMemory()\n\t\treturn fmt.Errorf(\"failed to start docker MCP: %w\", errors.Join(err, disableErr))\n\t}\n\n\tif err := ws.Cfg.PersistDockerMCPConfig(mcpConfig); err != nil {\n\t\tdisableErr := mcptools.DisableSingle(ws.Cfg, config.DockerMCPName)\n\t\tws.Cfg.RemoveDockerMCPInMemory()\n\t\treturn fmt.Errorf(\"docker MCP started but failed to persist configuration: %w\", errors.Join(err, disableErr))\n\t}\n\n\tpublishConfigChanged(ws)\n\treturn nil\n}\n\n// DisableDockerMCP closes the Docker MCP client, removes the\n// configuration, and persists the change.\nfunc (b *Backend) DisableDockerMCP(workspaceID string) error {\n\tws, err := b.GetWorkspace(workspaceID)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif err := mcptools.DisableSingle(ws.Cfg, config.DockerMCPName); err != nil {\n\t\treturn fmt.Errorf(\"failed to disable docker MCP: %w\", err)\n\t}\n","sourceCodeStart":223,"sourceCodeEnd":259,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/backend/config.go#L223-L259","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"info, err := os.Stat(configDir)\nif err != nil || !info.IsDir() {\n    return fmt.Errorf(\"config dir missing: %s\", configDir)\n}\ntest := filepath.Join(configDir, \".write-test\")\nif err := os.WriteFile(test, nil, 0o644); err != nil {\n    return fmt.Errorf(\"config dir not writable: %w\", err)\n}\nos.Remove(test)","typeGuard":"func IsPersistErr(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"failed to persist configuration\")\n}","tryCatchPattern":"if err := backend.EnableDockerMCP(ctx, wsID, cfg); err != nil {\n    if strings.Contains(err.Error(), \"failed to persist\") {\n        // startup succeeded; state was rolled back — safe to retry after fixing FS\n    }\n    return err\n}","preventionTips":["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."],"tags":["mcp","docker","persistence","filesystem"],"backgroundTag":"config-persist-failed","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}