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 scheme

View on GitHub (pinned to 5cf97d0d15)

Solutions

  1. Check ownership/permissions of the existing config file (chown/chmod so your user can write it)
  2. Ensure the config path is a file, not a directory
  3. Free disk space / fix disk errors if the FS reports I/O failure
  4. 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

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.