chenhg5/cc-connect · error

read config: %w

Error message

read config: %w

What it means

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.

Source

Thrown at config/config.go:1218

func SaveActiveProvider(projectName, providerName string) error {
	configMu.Lock()
	defer configMu.Unlock()
	return patchProjectAgentOption(projectName, "provider", providerName)
}

// SaveProviderModel persists the selected model for a provider in a project.
// It first looks in the project's inline providers, then falls back to
// global [[providers]] if the provider is referenced via provider_refs.
// Uses surgical text editing to preserve comments and unknown fields.
func SaveProviderModel(projectName, providerName, model string) error {
	configMu.Lock()
	defer configMu.Unlock()
	if ConfigPath == "" {
		return fmt.Errorf("config path not set")
	}
	data, err := os.ReadFile(ConfigPath)
	if err != nil {
		return fmt.Errorf("read config: %w", err)
	}
	raw := string(data)
	cfg := &Config{}
	if err := toml.Unmarshal(data, cfg); err != nil {
		return fmt.Errorf("parse config: %w", err)
	}

	projectIdx := -1
	for i := range cfg.Projects {
		if cfg.Projects[i].Name == projectName {
			projectIdx = i
			break
		}
	}
	if projectIdx < 0 {
		return fmt.Errorf("project %q not found in config", projectName)
	}

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Verify the path in the wrapped error exists: ls the exact path from ConfigPath
  2. Fix file permissions so the process user can read the file
  3. Correct the ConfigPath/--config value and retry
  4. Restore the config file from backup if it was deleted

Example fix

// before
config.ConfigPath = "/etc/cc-connect/confg.toml" // typo
// after
config.ConfigPath = "/etc/cc-connect/config.toml"
Defensive patterns

Strategy: try-catch

Validate before calling

if _, err := os.Stat(config.ConfigPath); err != nil {
	return fmt.Errorf("config unreadable: %w", err)
}

Try / catch

if err := config.SaveProviderModel(p, prov, model); err != nil {
	var pe *fs.PathError
	if errors.As(err, &pe) { // wrapped by 'read config:'
		log.Printf("fix path/permissions: %v", pe)
	}
	return err
}

Prevention

When it happens

Trigger: os.ReadFile(ConfigPath) fails inside SaveProviderModel: file deleted/moved after startup, wrong ConfigPath value, insufficient read permission, or disk/IO error.

Common situations: 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.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/a38bd0e57878ad08. Report an issue: GitHub.