alibaba/open-code-review · error

expected '{' in path_rule_map: %w

Error message

expected '{' in path_rule_map: %w

What it means

SystemRule.UnmarshalJSON's ordered-key parser failed at its first json.Decoder.Token() call while reading the opening brace of the path_rule_map value. The %w wraps the decoder's error (unexpected EOF, invalid character), meaning path_rule_map is present in the JSON but its value is not a well-formed JSON object. Order preservation for PathRules requires a streaming decode, so a broken value aborts unmarshalling entirely.

Source

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

	}
	r.DefaultRule = wrapper.DefaultRule

	// Use json.Decoder with UseNumber to preserve order of path_rule_map keys.
	var raw map[string]json.RawMessage
	if err := json.Unmarshal(data, &raw); err != nil {
		return err
	}
	mapData, ok := raw["path_rule_map"]
	if !ok || len(mapData) == 0 || string(mapData) == "null" {
		return nil
	}

	// Parse ordered keys using a streaming decoder.
	dec := json.NewDecoder(strings.NewReader(string(mapData)))
	// Read opening '{'
	t, err := dec.Token()
	if err != nil {
		return fmt.Errorf("expected '{' in path_rule_map: %w", err)
	}
	if t != json.Delim('{') {
		return fmt.Errorf("expected '{' in path_rule_map, got %v", t)
	}
	for dec.More() {
		// Read key
		keyTok, err := dec.Token()
		if err != nil {
			return fmt.Errorf("read path_rule_map key: %w", err)
		}
		key, ok := keyTok.(string)
		if !ok {
			return fmt.Errorf("expected string key in path_rule_map, got %T", keyTok)
		}
		// Read value
		var value string
		if err := dec.Decode(&value); err != nil {
			return fmt.Errorf("read path_rule_map value for %q: %w", key, err)

View on GitHub (pinned to 5cf97d0d15)

Solutions

  1. Validate the whole rules file with a JSON linter / 'jq .' before loading
  2. Check the path_rule_map value specifically — it must be a complete {"pattern":"rule"} object
  3. Fix truncation or stray characters around the path_rule_map block
  4. If path_rule_map is optional, either omit the key or set it to null (both are handled) rather than an empty/broken value

Example fix

// before (truncated)
"path_rule_map": {"*.go": "golang"
// after
"path_rule_map": {"*.go": "golang.md"}
Defensive patterns

Strategy: validation

Validate before calling

func validRulesConfig(data []byte) error {
    var probe map[string]json.RawMessage
    if err := json.Unmarshal(data, &probe); err != nil { return err }
    m, ok := probe["path_rule_map"]
    if !ok || string(m) == "null" { return nil }
    var obj map[string]string
    return json.Unmarshal(m, &obj) // catches truncated/broken objects early
}

Type guard

func isPathRuleMap(v json.RawMessage) bool {
    var obj map[string]string
    return len(v) > 0 && string(v) != "null" && json.Unmarshal(v, &obj) == nil
}

Try / catch

rule, err := rules.LoadDefault()
if err != nil {
    var dec *json.SyntaxError
    if errors.As(err, &dec) {
        return fmt.Errorf("malformed rules config at offset %d: %w", dec.Offset, err)
    }
    return err
}

Prevention

When it happens

Trigger: Custom rules JSON where "path_rule_map" is present but its value is syntactically invalid JSON (truncated file, missing closing brace, stray characters), so dec.Token() errors instead of returning a Delim.

Common situations: Hand-edited rules files saved mid-edit; config generated by a script that emitted invalid JSON; copy-paste that dropped the closing '}' or merged two objects.

Related errors


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