alibaba/open-code-review · error

read global rule %s: %w

Error message

read global rule %s: %w

What it means

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.

Source

Thrown at internal/config/rules/system_rules.go:383

			f.Exclude = append(f.Exclude, strings.ToLower(p))
		}
		return f
	}
	return nil
}

func loadGlobalRule() (*ProjectRule, error) {
	home, err := os.UserHomeDir()
	if err != nil {
		return nil, nil
	}
	path := filepath.Join(home, ".opencodereview", "rule.json")
	data, err := os.ReadFile(path)
	if err != nil {
		if os.IsNotExist(err) {
			return nil, nil
		}
		return nil, fmt.Errorf("read global rule %s: %w", path, err)
	}
	var pr ProjectRule
	if err := json.Unmarshal(data, &pr); err != nil {
		return nil, fmt.Errorf("unmarshal global rule: %w", err)
	}
	resolveRuleEntries(pr.Rules, filepath.Dir(path), "")
	return &pr, nil
}

func loadRuleFile(path string) (*ProjectRule, error) {
	data, err := os.ReadFile(path)
	if err != nil {
		return nil, fmt.Errorf("read rule file %s: %w", path, err)
	}
	var pr ProjectRule
	if err := json.Unmarshal(data, &pr); err != nil {
		return nil, fmt.Errorf("unmarshal rule file %s: %w", path, err)
	}

View on GitHub (pinned to 5cf97d0d15)

Solutions

  1. Check the file: ls -la ~/.opencodereview/rule.json — if it's a directory, remove it and create a regular JSON file
  2. Fix permissions so the running user can read it (chmod u+r)
  3. Verify $HOME points to the intended directory; the path in the error message shows exactly what was opened

Example fix

// before: rule.json is a directory or unreadable
$ ls -la ~/.opencodereview/rule.json  # drwxr-xr-x
// after
$ rm -rf ~/.opencodereview/rule.json
$ echo '{"rules": []}' > ~/.opencodereview/rule.json
Defensive patterns

Strategy: try-catch

Validate before calling

p := filepath.Join(os.Getenv("HOME"), ".opencodereview", "rule.json")
if fi, err := os.Stat(p); err == nil && fi.IsDir() {
	return fmt.Errorf("%s is a directory; expected a JSON file", p)
}
if fi, err := os.Stat(p); err == nil && fi.Mode().Perm()&0o400 == 0 {
	return fmt.Errorf("%s is not readable by the current user", p)
}

Try / catch

// loadGlobalRule treats ErrNotExist as 'no config'; wrap the call site:
pr, err := loadGlobalRule()
if err != nil {
	if errors.Is(err, os.ErrPermission) {
		log.Printf("warning: cannot read global rule (permissions): %v — continuing without it", err)
	} else {
		return err
	}
}

Prevention

When it happens

Trigger: 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.

Common situations: 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).

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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