alibaba/open-code-review · error
unmarshal project rule: %w
Error message
unmarshal project rule: %w
What it means
The rule.json contents are unmarshaled into ProjectRule with encoding/json. Any JSON syntax or type error (trailing commas, unquoted keys, wrong types for fields) produces this wrapped error. Unlike earlier failures there is no NotExist escape — a present but invalid rule file always fails the resolver.
Source
Thrown at internal/config/rules/system_rules.go:439
return nil, nil
}
return nil, fmt.Errorf("resolve project rule %s: %w", path, err)
}
if !pathutil.WithinBase(confineRoot, resolved) {
fmt.Fprintf(os.Stderr, "[ocr] WARNING: project rule file escapes repo dir: %s\n", path)
return nil, nil
}
data, err := os.ReadFile(resolved)
if err != nil {
if os.IsNotExist(err) {
return nil, nil
}
return nil, fmt.Errorf("read project rule %s: %w", path, err)
}
var pr ProjectRule
if err := json.Unmarshal(data, &pr); err != nil {
return nil, fmt.Errorf("unmarshal project rule: %w", err)
}
resolveRuleEntries(pr.Rules, repoDir, confineRoot)
return &pr, nil
}
// Resolve checks each layer in priority order; first match wins. User rules
// replace the system rule by default; rules with merge_system_rule keep the
// matched system rule alongside the user rule.
func (c *composedResolver) Resolve(path string) string {
for _, layer := range []*ProjectRule{c.custom, c.project, c.global} {
if entry := matchProjectRuleEntry(layer, path); entry != nil {
if entry.MergeSystemRule {
return c.mergeWithSystemRule(path, entry.Rule)
}
return entry.Rule
}
}
return c.system.Resolve(path)View on GitHub (pinned to 5cf97d0d15)
Solutions
- Validate the JSON: `jq . .opencodereview/rule.json` or paste into a JSON linter
- Remove comments/trailing commas — rule.json must be strict JSON
- Check field types match the ProjectRule struct (rules must be an array of objects)
- Re-copy a known-good rule.json from the repo template
Example fix
// before (rule.json)
{ "rules": [ { "id": "r1", } ] } // trailing comma
// after
{ "rules": [ { "id": "r1" } ] } Defensive patterns
Strategy: validation
Validate before calling
func validateRuleJSON(path string) error {
data, err := os.ReadFile(path)
if err != nil { return err }
var pr rules.ProjectRule
if err := json.Unmarshal(data, &pr); err != nil {
return fmt.Errorf("%s: invalid JSON: %w", path, err)
}
return nil
}
// run in CI: go run ./cmd/validate-rule .opencodereview/rule.json Try / catch
pr, err := loadProjectRule(repoDir)
if err != nil {
var syn *json.SyntaxError
if errors.As(err, &syn) {
fmt.Fprintf(os.Stderr, "JSON syntax error at offset %d: %v\n", syn.Offset, syn)
}
return err
} Prevention
- Lint rule.json with `jq .` in pre-commit hooks
- Never put comments or trailing commas in rule.json
- Validate after every hand edit: `jq empty .opencodereview/rule.json`
- Keep a schema-checked template of rule.json in the repo
When it happens
Trigger: json.Unmarshal of .opencodereview/rule.json fails because the file is not valid JSON or fields in ProjectRule have mismatched types (e.g. "rules": "x" instead of an array).
Common situations: Hand-edited rule.json with a missing comma or comment (JSON has no comments); a rule file copied from YAML; an editor that saved a BOM or truncated the file; schema drift after upgrading ocr to a version with stricter types.
Understand the failure class
Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.
Related errors
- parse config: %w
- parse app config: %w
- load app config: %w
- unmarshal task_template manifest: %w
- unmarshal default scan template: %w
AI-assisted analysis of alibaba/open-code-review@5cf97d0d15 (2026-09-02).
Data as JSON: /api/errors/5b5bf3f6793a52ae.
Report an issue: GitHub.