{"record":{"id":"7dfa4e14b742f007","repo":"alibaba/open-code-review","slug":"write-config-w","errorCode":null,"errorMessage":"write config: %w","messagePattern":"write config: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/opencodereview/provider_cmd.go","lineNumber":429,"sourceCode":"\tif err := saveConfig(configPath, cfg); err != nil {\n\t\treturn err\n\t}\n\n\tfmt.Printf(\"\\nModel set to: %s\\n\", selectedModel)\n\treturn nil\n}\n\nfunc saveConfig(path string, cfg *Config) error {\n\tdir := filepath.Dir(path)\n\tif err := os.MkdirAll(dir, 0o755); err != nil {\n\t\treturn fmt.Errorf(\"create config dir: %w\", err)\n\t}\n\tdata, err := json.MarshalIndent(cfg, \"\", \"    \")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"marshal config: %w\", err)\n\t}\n\tif err := os.WriteFile(path, data, 0o600); err != nil {\n\t\treturn fmt.Errorf(\"write config: %w\", err)\n\t}\n\tif err := os.Chmod(path, 0o600); err != nil {\n\t\treturn fmt.Errorf(\"chmod config: %w\", err)\n\t}\n\treturn nil\n}\n\nfunc maskKey(key string) string {\n\tif key == \"\" {\n\t\treturn \"(not set)\"\n\t}\n\tif len(key) <= 8 {\n\t\treturn \"***\"\n\t}\n\treturn key[:4] + \"***\" + key[len(key)-4:]\n}\n\n// validateBaseURL checks that a provider Base URL has an http or https scheme","sourceCodeStart":411,"sourceCodeEnd":447,"githubUrl":"https://github.com/alibaba/open-code-review/blob/5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f/cmd/opencodereview/provider_cmd.go#L411-L447","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)"],"exampleFix":"// before\nls -l ~/.config/ocr/config.json  # -rw------- root root\n$ ocr config set effort high\n// error: write config: open ...: permission denied\n// after\n$ sudo chown $USER ~/.config/ocr/config.json\n$ ocr config set effort high","handlingStrategy":"validation","validationCode":"if info, err := os.Stat(path); err == nil {\n    if info.IsDir() { return fmt.Errorf(\"%s is a directory\", path) }\n    if err := syscall.Access(path, os.O_WRONLY); err != nil {\n        return fmt.Errorf(\"config file %s not writable: %w\", path, err)\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := saveConfig(path, cfg); err != nil {\n    if errors.Is(err, fs.ErrPermission) {\n        fmt.Fprintln(os.Stderr, \"run: sudo chown $USER <config path>, then retry\")\n    }\n    return err\n}","preventionTips":["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"],"tags":["filesystem","permissions","config"],"backgroundTag":"file-write-permission-denied","analyzedSha":"5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f","analyzedAt":"2026-09-02T02:08:09.116Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}