{"record":{"id":"c5b3ffba24633894","repo":"gastownhall/beads","slug":"error-reading-config-file-w","errorCode":null,"errorMessage":"error reading config file: %w","messagePattern":"error reading config file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/config/config.go","lineNumber":361,"sourceCode":"\tv.SetDefault(\"ai.base_url\", \"\")\n\n\t// List command defaults\n\tv.SetDefault(\"list.limit\", 50)\n\n\t// Output configuration (GH#1384)\n\t// Controls title display in command feedback messages.\n\t// 0 = hide title, N > 0 = truncate to N chars with \"…\"\n\tv.SetDefault(\"output.title-length\", 255)\n\n\t// External projects for cross-project dependency resolution (bd-h807)\n\t// Maps project names to paths for resolving external: blocked_by references\n\tv.SetDefault(\"external_projects\", map[string]string{})\n\n\t// Load config files: lowest priority first, each MergeInConfig overwrites\n\tif len(configPaths) > 0 {\n\t\tv.SetConfigFile(configPaths[0])\n\t\tif err := v.ReadInConfig(); err != nil {\n\t\t\treturn fmt.Errorf(\"error reading config file: %w\", err)\n\t\t}\n\t\tdebug.Logf(\"Debug: loaded config from %s\\n\", configPaths[0])\n\n\t\tfor _, p := range configPaths[1:] {\n\t\t\tv.SetConfigFile(p)\n\t\t\tif err := v.MergeInConfig(); err != nil {\n\t\t\t\treturn fmt.Errorf(\"error merging config file %s: %w\", p, err)\n\t\t\t}\n\t\t\tdebug.Logf(\"Debug: merged config from %s\\n\", p)\n\t\t}\n\n\t\t// Restore primary config path as ConfigFileUsed (used by SaveConfigValue,\n\t\t// ResolveExternalProjectPath, etc.)\n\t\tv.SetConfigFile(primaryConfigPath)\n\n\t\t// Merge local config overrides if present (config.local.yaml)\n\t\t// This allows machine-specific settings without polluting tracked config\n\t\tlocalConfigPath := filepath.Join(filepath.Dir(primaryConfigPath), \"config.local.yaml\")","sourceCodeStart":343,"sourceCodeEnd":379,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/config/config.go#L343-L379","documentation":"Initialize wraps any error returned by viper's ReadInConfig when loading the first (primary) config file. It means the primary config file exists but could not be read or parsed — bad YAML syntax, unreadable permissions, or a directory passed as a config path. The underlying viper error is preserved via %w so callers can inspect the cause.","triggerScenarios":"Calling Initialize with a configPaths[0] file that is malformed YAML, has no read permission, is a directory, or an empty/corrupt file that viper's ReadInConfig rejects.","commonSituations":"Hand-edited config.yaml with broken indentation or tabs; a config file truncated by a crashed editor or disk-full write; permissions changed by another user; passing a path with the wrong extension or encoding (UTF-16, BOM issues).","solutions":["Open the file named in the wrapped error and fix the YAML syntax (validate with yamllint or a YAML parser).","Check file permissions and ownership: ensure the current user can read the file.","Verify the path points to a regular file, not a directory or symlink to a missing target.","If the file is unrecoverable, restore it from version control or a backup, or delete it so defaults are used."],"exampleFix":"// before (config.yaml)\nrouting:\n\tmode: auto  # tab indentation breaks YAML\n// after\nrouting:\n  mode: auto  # use spaces","handlingStrategy":"validation","validationCode":"info, err := os.Stat(configPath)\nif err != nil { return err }\nif info.IsDir() { return fmt.Errorf(\"%s is a directory, not a file\", configPath) }\ndata, err := os.ReadFile(configPath)\nif err != nil { return err }\nif err := yaml.Unmarshal(data, map[string]interface{}{}); err != nil {\n    return fmt.Errorf(\"config %s has invalid YAML: %w\", configPath, err)\n}","typeGuard":null,"tryCatchPattern":"if err := config.Initialize(paths); err != nil {\n    var perr *fs.PathError\n    if errors.As(err, &perr) {\n        log.Fatalf(\"cannot read %s: %v — fix or remove the file\", perr.Path, perr.Err)\n    }\n    return err\n}","preventionTips":["Validate config files with a YAML linter in CI or a git pre-commit hook.","Keep config files in version control so bad edits are diff-visible and revertible.","Write config files atomically (temp file + rename) to avoid truncated files.","Ensure the service user owns or can read all config paths."],"tags":["config","yaml","parse-error","viper"],"backgroundTag":"config-file-parse-error","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}