alibaba/open-code-review · error
write config: %w
Error message
write config: %w
What it means
saveConfig writes the marshaled JSON with os.WriteFile(path, data, 0o600); failure is wrapped as "write config". This is the standard file-write failure path: permission denied on the existing file, path is a directory, disk full, or the file was removed/replaced between operations.
Source
Thrown at cmd/opencodereview/provider_cmd.go:429
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)"
}
if len(key) <= 8 {
return "***"
}
return key[:4] + "***" + key[len(key)-4:]
}
// validateBaseURL checks that a provider Base URL has an http or https schemeView on GitHub (pinned to 5cf97d0d15)
Solutions
- Check ownership/permissions of the existing config file (chown/chmod so your user can write it)
- Ensure the config path is a file, not a directory
- Free disk space / fix disk errors if the FS reports I/O failure
- Use a writable config path (OCR_CONFIG or the tool's default under $HOME)
Example fix
// before ls -l ~/.config/ocr/config.json # -rw------- root root $ ocr config set effort high // error: write config: open ...: permission denied // after $ sudo chown $USER ~/.config/ocr/config.json $ ocr config set effort high
Defensive patterns
Strategy: validation
Validate before calling
if info, err := os.Stat(path); err == nil {
if info.IsDir() { return fmt.Errorf("%s is a directory", path) }
if err := syscall.Access(path, os.O_WRONLY); err != nil {
return fmt.Errorf("config file %s not writable: %w", path, err)
}
} Try / catch
if err := saveConfig(path, cfg); err != nil {
if errors.Is(err, fs.ErrPermission) {
fmt.Fprintln(os.Stderr, "run: sudo chown $USER <config path>, then retry")
}
return err
} Prevention
- Ensure the config file is owned by the invoking user (avoid mixed sudo usage)
- Keep the config path a regular file, not a directory
- Write config on a local, writable filesystem
- Verify disk space before automated config writes
When it happens
Trigger: Any saveConfig call (config set/unset, TUI saves) where os.WriteFile fails — config file exists but is not writable by the current user, the target path is a directory, or an I/O error occurs.
Common situations: Config file previously created by root (root-owned ~/.config/ocr/config.json); running under sudo inconsistently so ownership mismatches; read-only mounted home; antivirus/backup locks on Windows.
Understand the failure class
Background: "Permission denied" / "Failed to write" file errors: why a library can't write its files to disk (EACCES, EPERM, ENOSPC) and how to fix them — this error's family across 43 libraries.
Related errors
AI-assisted analysis of alibaba/open-code-review@5cf97d0d15 (2026-09-02).
Data as JSON: /api/errors/7dfa4e14b742f007.
Report an issue: GitHub.