{"record":{"id":"1331496cf83c1ca9","repo":"gastownhall/beads","slug":"reading-central-config-w","errorCode":null,"errorMessage":"reading central config: %w","messagePattern":"reading central config: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/configfile/central_config.go","lineNumber":42,"sourceCode":"\t\t}\n\t}\n\thome, err := os.UserHomeDir()\n\tif err != nil {\n\t\treturn \"\"\n\t}\n\treturn filepath.Join(home, \".config\", \"beads\", CentralConfigFileName)\n}\n\n// LoadCentralConfig reads the central server config from the given path.\n// Returns (nil, nil) if the file does not exist (graceful skip).\n// Returns an error only if the file exists but cannot be parsed.\nfunc LoadCentralConfig(path string) (*Config, error) {\n\tdata, err := os.ReadFile(path) // #nosec G304 - path from DefaultCentralConfigPath or env\n\tif os.IsNotExist(err) {\n\t\treturn nil, nil\n\t}\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"reading central config: %w\", err)\n\t}\n\n\tvar cfg Config\n\tif err := json.Unmarshal(data, &cfg); err != nil {\n\t\treturn nil, fmt.Errorf(\"parsing central config %s: %w\", path, err)\n\t}\n\treturn &cfg, nil\n}\n\n// ApplyCentralDefaults merges server-related fields from the central config\n// into the per-project config, but only for fields that are at their zero\n// value in the project config. Non-server fields (Database, DoltDatabase,\n// DoltDataDir, ProjectID, etc.) are never inherited from the central config\n// because they are inherently per-project.\n//\n// This is a no-op if central is nil.\nfunc ApplyCentralDefaults(project *Config, central *Config) {\n\tif central == nil {","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/configfile/central_config.go#L24-L60","documentation":"LoadCentralConfig wraps any non-ENOENT error from os.ReadFile of the central (shared) config file with \"reading central config: %w\". A missing file returns nil,nil, so this error means the file exists but could not be read (permissions, I/O, path issues).","triggerScenarios":"LoadCentralConfig(path) when the central config exists but os.ReadFile fails with e.g. EACCES, EISDIR, or a device error — path comes from DefaultCentralConfigPath or an env override.","commonSituations":"Central config in a shared/team location owned by another user or read-protected; path env var pointing at a directory; NFS/network mount failures.","solutions":["Check file permissions: `ls -l <path>` and add read permission (`chmod +r`)","Verify the path env override points at the JSON file, not a directory","If on a network mount, verify the mount is healthy or copy the config locally"],"exampleFix":"// before\nBD_CENTRAL_CONFIG=/etc/bd/central.d LoadCentralConfig(path)\n// after\nBD_CENTRAL_CONFIG=/etc/bd/central.json LoadCentralConfig(path)","handlingStrategy":"try-catch","validationCode":"fi, err := os.Stat(path)\nif err != nil { /* path bad */ } else if fi.IsDir() { /* env var points at a directory */ } else if fi.Mode().Perm()&0o444 == 0 { /* unreadable */ }","typeGuard":null,"tryCatchPattern":"cfg, err := bd.LoadCentralConfig(path)\nif err != nil {\n    if errors.Is(err, fs.ErrPermission) { /* chmod +r or run as owner */ }\n    // non-nil cfg is guaranteed unmodified; fail safe\n    return err\n}","preventionTips":["Verify env path overrides point at a JSON file, not a directory","Keep central config world-readable but not world-writable","Avoid placing shared config on flaky network mounts"],"tags":["config","filesystem","permissions"],"backgroundTag":"config-file-read-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}