{"record":{"id":"177758342e91d2ee","repo":"chenhg5/cc-connect","slug":"config-path-not-set","errorCode":null,"errorMessage":"config path not set","messagePattern":"config path not set","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"config/config.go","lineNumber":1214,"sourceCode":"}\n\n// SaveActiveProvider persists the active provider name for a project.\n// It uses surgical text editing to preserve comments and unknown fields.\nfunc SaveActiveProvider(projectName, providerName string) error {\n\tconfigMu.Lock()\n\tdefer configMu.Unlock()\n\treturn patchProjectAgentOption(projectName, \"provider\", providerName)\n}\n\n// SaveProviderModel persists the selected model for a provider in a project.\n// It first looks in the project's inline providers, then falls back to\n// global [[providers]] if the provider is referenced via provider_refs.\n// Uses surgical text editing to preserve comments and unknown fields.\nfunc SaveProviderModel(projectName, providerName, model string) error {\n\tconfigMu.Lock()\n\tdefer configMu.Unlock()\n\tif ConfigPath == \"\" {\n\t\treturn fmt.Errorf(\"config path not set\")\n\t}\n\tdata, err := os.ReadFile(ConfigPath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"read config: %w\", err)\n\t}\n\traw := string(data)\n\tcfg := &Config{}\n\tif err := toml.Unmarshal(data, cfg); err != nil {\n\t\treturn fmt.Errorf(\"parse config: %w\", err)\n\t}\n\n\tprojectIdx := -1\n\tfor i := range cfg.Projects {\n\t\tif cfg.Projects[i].Name == projectName {\n\t\t\tprojectIdx = i\n\t\t\tbreak\n\t\t}\n\t}","sourceCodeStart":1196,"sourceCodeEnd":1232,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/config/config.go#L1196-L1232","documentation":"SaveProviderModel refuses to run when the package-level ConfigPath variable has not been initialized. The function performs surgical text edits on the TOML file at ConfigPath, so without a path there is nothing to safely modify, and it fails rather than guessing a location.","triggerScenarios":"Calling SaveProviderModel(project, provider, model) before LoadConfig/any code set config.ConfigPath — typically a library consumer invoking save APIs without loading config first, or a binary invoked with no config flag.","commonSituations":"Running a CLI subcommand that persists model changes without the --config flag; tests calling SaveProviderModel directly without setting ConfigPath; refactoring that removed the init call that sets ConfigPath.","solutions":["Ensure LoadConfig (or explicit assignment to config.ConfigPath) runs before SaveProviderModel","Pass/point the binary at a config file path (e.g. --config flag) at startup","In tests, set config.ConfigPath to a temp file path in setup"],"exampleFix":"// before\nconfig.SaveProviderModel(\"proj\", \"kimi\", \"model-x\") // ConfigPath == \"\"\n// after\nconfig.ConfigPath = \"/etc/cc-connect/config.toml\"\nconfig.SaveProviderModel(\"proj\", \"kimi\", \"model-x\")","handlingStrategy":"type-guard","validationCode":"if config.ConfigPath == \"\" {\n\treturn errors.New(\"call LoadConfig or set config.ConfigPath first\")\n}","typeGuard":"func canSave() bool { return config.ConfigPath != \"\" }","tryCatchPattern":"if err := config.SaveProviderModel(p, prov, model); err != nil {\n\tif err.Error() == \"config path not set\" {\n\t\tconfig.LoadConfig(defaultPath) // then retry\n\t}\n\treturn err\n}","preventionTips":["Always run LoadConfig at process start before any save API","Set ConfigPath in test setup with a temp file","Centralize save calls behind a helper that ensures ConfigPath is set"],"tags":["config","state","initialization"],"backgroundTag":"missing-config-value","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}