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

  1. Validate the JSON: `jq . .opencodereview/rule.json` or paste into a JSON linter
  2. Remove comments/trailing commas — rule.json must be strict JSON
  3. Check field types match the ProjectRule struct (rules must be an array of objects)
  4. 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

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


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