{"record":{"id":"a38bd0e57878ad08","repo":"chenhg5/cc-connect","slug":"read-config-w","errorCode":null,"errorMessage":"read config: %w","messagePattern":"read config: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"config/config.go","lineNumber":1218,"sourceCode":"func 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}\n\tif projectIdx < 0 {\n\t\treturn fmt.Errorf(\"project %q not found in config\", projectName)\n\t}\n","sourceCodeStart":1200,"sourceCodeEnd":1236,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/config/config.go#L1200-L1236","documentation":"SaveProviderModel wraps any os.ReadFile failure on ConfigPath with 'read config: %w'. The file could not be read at all (missing, permission, or I/O error), so the surgical edit cannot proceed and the underlying OS error is preserved for diagnosis.","triggerScenarios":"os.ReadFile(ConfigPath) fails inside SaveProviderModel: file deleted/moved after startup, wrong ConfigPath value, insufficient read permission, or disk/IO error.","commonSituations":"Pointing the app at a non-existent config path; running the daemon as a user without read permission on the config; config removed by a cleanup script while the process is running.","solutions":["Verify the path in the wrapped error exists: ls the exact path from ConfigPath","Fix file permissions so the process user can read the file","Correct the ConfigPath/--config value and retry","Restore the config file from backup if it was deleted"],"exampleFix":"// before\nconfig.ConfigPath = \"/etc/cc-connect/confg.toml\" // typo\n// after\nconfig.ConfigPath = \"/etc/cc-connect/config.toml\"","handlingStrategy":"try-catch","validationCode":"if _, err := os.Stat(config.ConfigPath); err != nil {\n\treturn fmt.Errorf(\"config unreadable: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if err := config.SaveProviderModel(p, prov, model); err != nil {\n\tvar pe *fs.PathError\n\tif errors.As(err, &pe) { // wrapped by 'read config:'\n\t\tlog.Printf(\"fix path/permissions: %v\", pe)\n\t}\n\treturn err\n}","preventionTips":["Check file existence/permissions at startup health checks","Run the daemon as a user with read access to the config","Guard the config file against deletion by cleanup scripts"],"tags":["config","file-io","read-error"],"backgroundTag":"file-read-failed","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"}