{"record":{"id":"2525ccc3f6aea99d","repo":"charmbracelet/crush","slug":"failed-to-persist-docker-mcp-configuration-w","errorCode":null,"errorMessage":"failed to persist docker mcp configuration: %w","messagePattern":"failed to persist docker mcp configuration: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/config/docker_mcp.go","lineNumber":105,"sourceCode":"\t\treturn MCPConfig{}, fmt.Errorf(\"docker mcp is not available, please ensure docker is installed and 'docker mcp version' succeeds\")\n\t}\n\n\tmcpConfig := DockerMCPConfig()\n\t// In-memory only; persistence happens in PersistDockerMCPConfig.\n\ts.mutateInMemory(func(c *Config) {\n\t\tif c.MCP == nil {\n\t\t\tc.MCP = make(map[string]MCPConfig)\n\t\t}\n\t\tc.MCP[DockerMCPName] = mcpConfig\n\t})\n\treturn mcpConfig, nil\n}\n\n// PersistDockerMCPConfig persists a previously prepared Docker MCP\n// configuration to the global config file.\nfunc (s *ConfigStore) PersistDockerMCPConfig(mcpConfig MCPConfig) error {\n\tif err := s.SetConfigField(ScopeGlobal, \"mcp.\"+DockerMCPName, mcpConfig); err != nil {\n\t\treturn fmt.Errorf(\"failed to persist docker mcp configuration: %w\", err)\n\t}\n\treturn nil\n}\n\n// EnableDockerMCP adds Docker MCP configuration and persists it.\nfunc (s *ConfigStore) EnableDockerMCP() error {\n\tmcpConfig, err := s.PrepareDockerMCPConfig()\n\tif err != nil {\n\t\treturn err\n\t}\n\tif err := s.PersistDockerMCPConfig(mcpConfig); err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n// DisableDockerMCP removes Docker MCP configuration and persists the change.\nfunc (s *ConfigStore) DisableDockerMCP() error {","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/config/docker_mcp.go#L87-L123","documentation":"Wraps an error from ConfigStore.SetConfigField while persisting the staged Docker MCP config under the `mcp.docker` key of the global config file. Preparation (in-memory) succeeded, but writing the global config failed — usually a filesystem or serialization problem.","triggerScenarios":"Calling PersistDockerMCPConfig (directly or via EnableDockerMCP) when the global config file cannot be written: read-only filesystem, permission denied on the config file/directory, corrupted config JSON, or disk full.","commonSituations":"~/.config/crush/ owned by root after a sudo run; config file made read-only; home directory on a read-only mount or full disk; JSON schema mismatch after a Crush version upgrade.","solutions":["Check permissions on the global config file/directory (ls -l ~/.config/crush/) and fix ownership/permissions.","Validate the existing global config file is valid JSON/TOML; fix or back it up and let Crush regenerate it.","Free disk space if the filesystem is full.","Retry EnableDockerMCP after fixing the filesystem; the in-memory staged config is re-prepared automatically."],"exampleFix":"// before\n$ ls -l ~/.config/crush/crush.json\n-rw-r--r-- 1 root root ... // owned by root\n// after\n$ sudo chown -R $USER ~/.config/crush\n$ crush docker mcp enable","handlingStrategy":"try-catch","validationCode":"cfgPath := globalConfigPath()\nif f, err := os.OpenFile(cfgPath, os.O_WRONLY, 0o644); err != nil {\n    return fmt.Errorf(\"global config not writable (%s): %w\", cfgPath, err)\n} else {\n    f.Close()\n}","typeGuard":"func isPermissionErr(err error) bool {\n    return errors.Is(err, os.ErrPermission) || errors.Is(err, syscall.EACCES) || errors.Is(err, syscall.EROFS)\n}","tryCatchPattern":"if err := store.PersistDockerMCPConfig(mcpCfg); err != nil {\n    var pErr *fs.PathError\n    if errors.As(err, &pErr) && isPermissionErr(pErr) {\n        log.Fatalf(\"cannot write %s: check ownership (was a sudo run involved?)\", pErr.Path)\n    }\n    return err\n}","preventionTips":["Never run Crush with sudo; fix ownership of ~/.config/crush if root-owned.","Keep the config directory writable by the current user (0o700 dir, 0o600 file).","Monitor disk space on the home filesystem.","Back up and validate the global config after version upgrades."],"tags":["config","filesystem","permissions","persistence"],"backgroundTag":"config-write-failed","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}