{"record":{"id":"5ee7037487194539","repo":"gastownhall/beads","slug":"config-not-initialized","errorCode":null,"errorMessage":"config not initialized","messagePattern":"config not initialized","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/config/config.go","lineNumber":635,"sourceCode":"\tcase SourceFlag:\n\t\toverrideDesc = \"command-line flag\"\n\tcase SourceEnvVar:\n\t\toverrideDesc = \"environment variable\"\n\tdefault:\n\t\toverrideDesc = string(override.OverriddenBy)\n\t}\n\n\t// Always emit to stderr when verbose mode is enabled (caller guards on verbose)\n\tfmt.Fprintf(os.Stderr, \"Config: %s overridden by %s (was: %v from %s, now: %v)\\n\",\n\t\toverride.Key, overrideDesc, override.OriginalValue, sourceDesc, override.EffectiveValue)\n}\n\n// SaveConfigValue sets a key-value pair and writes it to the config file.\n// If no config file is currently loaded, it creates config.yaml in the given beadsDir.\n// Only the specified key is modified; other file contents are preserved.\nfunc SaveConfigValue(key string, value interface{}, beadsDir string) error {\n\tif v == nil {\n\t\treturn fmt.Errorf(\"config not initialized\")\n\t}\n\tv.Set(key, value)\n\n\tconfigPath := v.ConfigFileUsed()\n\tif configPath == \"\" {\n\t\tconfigPath = filepath.Join(beadsDir, \"config.yaml\")\n\t\tv.SetConfigFile(configPath)\n\t}\n\n\t// Read existing file contents to avoid dumping all merged viper state\n\t// (defaults, env vars, overrides) into the config file.\n\texisting := make(map[string]interface{})\n\tif data, err := os.ReadFile(filepath.Clean(configPath)); err == nil {\n\t\t_ = yaml.Unmarshal(data, &existing)\n\t}\n\n\t// Set the single key using dot-path splitting for nested keys (e.g. \"routing.mode\").\n\tsetNestedKey(existing, key, value)","sourceCodeStart":617,"sourceCodeEnd":653,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/config/config.go#L617-L653","documentation":"SaveConfigValue requires the package-level viper instance to have been initialized by calling Initialize first. If the singleton `v` is still nil, saving is impossible and this sentinel error is returned. It is a programming/lifecycle error, not a data error.","triggerScenarios":"Calling SaveConfigValue without a prior successful call to Initialize in the same process, or after Initialize failed before assigning `v`.","commonSituations":"A CLI subcommand or test calls SaveConfigValue directly, bypassing the normal bootstrap; a plugin invokes the save API in a process where config was never loaded.","solutions":["Call config.Initialize (with the appropriate config paths/beads dir) before SaveConfigValue.","Check the error returned by Initialize — if it failed, `v` may remain nil.","In tests, use the same setup helper other config tests use to initialize the singleton before saving."],"exampleFix":"// before\nerr := config.SaveConfigValue(\"routing.mode\", \"auto\", beadsDir)\n// after\nif err := config.Initialize([]string{configPath}); err != nil {\n    return err\n}\nerr := config.SaveConfigValue(\"routing.mode\", \"auto\", beadsDir)","handlingStrategy":"try-catch","validationCode":"// ensure config is initialized in main/setup before any save:\nif err := config.Initialize(configPaths); err != nil {\n    return fmt.Errorf(\"config bootstrap failed: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if err := config.SaveConfigValue(key, value, beadsDir); err != nil {\n    if err.Error() == \"config not initialized\" {\n        if ierr := config.Initialize(configPaths); ierr != nil {\n            return ierr\n        }\n        return config.SaveConfigValue(key, value, beadsDir)\n    }\n    return err\n}","preventionTips":["Centralize config bootstrap in one entry point (main or a setup package).","Never call save APIs from init() or package-level vars that run before Initialize.","In tests, share a setup helper that initializes config before save calls.","Check the error from Initialize and fail fast instead of continuing with nil state."],"tags":["config","initialization","lifecycle","state"],"backgroundTag":"config-not-initialized","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}