alibaba/open-code-review · error

create config dir

Error message

create config dir: %w

What it means

saveConfig creates the parent directory of the config file with os.MkdirAll(dir, 0o755) before writing; if that fails the error is wrapped as "create config dir". This is an I/O/permission failure on the filesystem, raised before any JSON is produced.

Solutions

  1. Check permissions on the parent directory and ensure the user can create the config dir
  2. Ensure the config path's parent is a directory, not an existing file
  3. Fix HOME/XDG or pass a config path in a writable location
  4. Free disk space if the filesystem is full

Example fix

// before
OCR_CONFIG=/etc/ocr/config.json ocr config set provider openai
// error: create config dir: mkdir /etc/ocr: permission denied
// after
OCR_CONFIG=~/.config/ocr/config.json ocr config set provider openai
Defensive patterns

Strategy: validation

Validate before calling

dir := filepath.Dir(cfgPath)
if info, err := os.Stat(dir); err == nil && !info.IsDir() {
    return fmt.Errorf("%s exists and is not a directory", dir)
}
if err := os.MkdirAll(dir, 0o755); err != nil {
    return fmt.Errorf("cannot create config dir %s: %w", dir, err)
}

Try / catch

if err := saveConfig(path, cfg); err != nil {
    var pe *os.PathError
    if errors.As(err, &pe) && errors.Is(pe.Err, fs.ErrPermission) {
        fmt.Fprintf(os.Stderr, "no permission for %s — check ownership/HOME\n", path)
    }
    return err
}

Prevention

When it happens

Trigger: Calling saveConfig (via ocr config set, unset commands, or the provider/model TUIs) when the config directory cannot be created — e.g. path is inside a read-only directory, a file exists where a directory is expected, or permission is denied.

Common situations: HOME set to a non-writable path; config path pointing under a file like /etc/passwd/config.json; disk full or sandboxed CI runners with restricted write access.

Understand the failure class

Background: mkdir permission denied (EACCES): failed to create directory errors explained — this error's family across 32 libraries.

Related errors


AI-assisted analysis of alibaba/open-code-review@5cf97d0d15 (2026-09-02). Data as JSON: /api/errors/be25d0dcf4d18db0. Report an issue: GitHub.

Appendix: source

Thrown at cmd/opencodereview/provider_cmd.go:422

		if !llm.ModelListContains(registryModels, selectedModel) {
			entry.Models = ensureModelInList(entry.Models, selectedModel)
		}
		cfg.Providers[cfg.Provider] = entry
	}
	cfg.Model = selectedModel

	if err := saveConfig(configPath, cfg); err != nil {
		return err
	}

	fmt.Printf("\nModel set to: %s\n", selectedModel)
	return nil
}

func saveConfig(path string, cfg *Config) error {
	dir := filepath.Dir(path)
	if err := os.MkdirAll(dir, 0o755); err != nil {
		return fmt.Errorf("create config dir: %w", err)
	}
	data, err := json.MarshalIndent(cfg, "", "    ")
	if err != nil {
		return fmt.Errorf("marshal config: %w", err)
	}
	if err := os.WriteFile(path, data, 0o600); err != nil {
		return fmt.Errorf("write config: %w", err)
	}
	if err := os.Chmod(path, 0o600); err != nil {
		return fmt.Errorf("chmod config: %w", err)
	}
	return nil
}

func maskKey(key string) string {
	if key == "" {
		return "(not set)"
	}

View on GitHub (pinned to 5cf97d0d15)