{"record":{"id":"c81cd7cbd692a406","repo":"alibaba/open-code-review","slug":"read-global-rule-s-w","errorCode":null,"errorMessage":"read global rule %s: %w","messagePattern":"read global rule (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/config/rules/system_rules.go","lineNumber":383,"sourceCode":"\t\t\tf.Exclude = append(f.Exclude, strings.ToLower(p))\n\t\t}\n\t\treturn f\n\t}\n\treturn nil\n}\n\nfunc loadGlobalRule() (*ProjectRule, error) {\n\thome, err := os.UserHomeDir()\n\tif err != nil {\n\t\treturn nil, nil\n\t}\n\tpath := filepath.Join(home, \".opencodereview\", \"rule.json\")\n\tdata, err := os.ReadFile(path)\n\tif err != nil {\n\t\tif os.IsNotExist(err) {\n\t\t\treturn nil, nil\n\t\t}\n\t\treturn nil, fmt.Errorf(\"read global rule %s: %w\", path, err)\n\t}\n\tvar pr ProjectRule\n\tif err := json.Unmarshal(data, &pr); err != nil {\n\t\treturn nil, fmt.Errorf(\"unmarshal global rule: %w\", err)\n\t}\n\tresolveRuleEntries(pr.Rules, filepath.Dir(path), \"\")\n\treturn &pr, nil\n}\n\nfunc loadRuleFile(path string) (*ProjectRule, error) {\n\tdata, err := os.ReadFile(path)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"read rule file %s: %w\", path, err)\n\t}\n\tvar pr ProjectRule\n\tif err := json.Unmarshal(data, &pr); err != nil {\n\t\treturn nil, fmt.Errorf(\"unmarshal rule file %s: %w\", path, err)\n\t}","sourceCodeStart":365,"sourceCodeEnd":401,"githubUrl":"https://github.com/alibaba/open-code-review/blob/5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f/internal/config/rules/system_rules.go#L365-L401","documentation":"loadGlobalRule reads ~/.opencodereview/rule.json; a missing file is tolerated (returns nil, nil), but any other read failure (permissions, is-a-directory, I/O error) is wrapped in this error with the full path. Unlike missing, these indicate a real environment problem.","triggerScenarios":"os.ReadFile on $HOME/.opencodereview/rule.json fails with an error other than fs.ErrNotExist — e.g. EACCES on a unreadable file, EISDIR because rule.json is a directory, or a symlink loop.","commonSituations":"rule.json created as a directory by mistake; file owned by root or with 000 permissions after restoring from backup; $HOME pointing at an unwritable/odd location (containers, CI).","solutions":["Check the file: ls -la ~/.opencodereview/rule.json — if it's a directory, remove it and create a regular JSON file","Fix permissions so the running user can read it (chmod u+r)","Verify $HOME points to the intended directory; the path in the error message shows exactly what was opened"],"exampleFix":"// before: rule.json is a directory or unreadable\n$ ls -la ~/.opencodereview/rule.json  # drwxr-xr-x\n// after\n$ rm -rf ~/.opencodereview/rule.json\n$ echo '{\"rules\": []}' > ~/.opencodereview/rule.json","handlingStrategy":"try-catch","validationCode":"p := filepath.Join(os.Getenv(\"HOME\"), \".opencodereview\", \"rule.json\")\nif fi, err := os.Stat(p); err == nil && fi.IsDir() {\n\treturn fmt.Errorf(\"%s is a directory; expected a JSON file\", p)\n}\nif fi, err := os.Stat(p); err == nil && fi.Mode().Perm()&0o400 == 0 {\n\treturn fmt.Errorf(\"%s is not readable by the current user\", p)\n}","typeGuard":null,"tryCatchPattern":"// loadGlobalRule treats ErrNotExist as 'no config'; wrap the call site:\npr, err := loadGlobalRule()\nif err != nil {\n\tif errors.Is(err, os.ErrPermission) {\n\t\tlog.Printf(\"warning: cannot read global rule (permissions): %v — continuing without it\", err)\n\t} else {\n\t\treturn err\n\t}\n}","preventionTips":["Check ls -la ~/.opencodereview/rule.json after restoring backups or changing $HOME","Never create rule.json as a directory; create it with a text editor or printf","In containers/CI, ensure $HOME points to a writable, readable location"],"tags":["filesystem","permissions","config"],"backgroundTag":"file-read-failed","analyzedSha":"5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f","analyzedAt":"2026-09-02T02:08:09.116Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}