{"record":{"id":"7e514d08109d5883","repo":"alibaba/open-code-review","slug":"expected-in-path-rule-map-w","errorCode":null,"errorMessage":"expected '{' in path_rule_map: %w","messagePattern":"expected '\\{' in path_rule_map: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/config/rules/system_rules.go","lineNumber":64,"sourceCode":"\t}\n\tr.DefaultRule = wrapper.DefaultRule\n\n\t// Use json.Decoder with UseNumber to preserve order of path_rule_map keys.\n\tvar raw map[string]json.RawMessage\n\tif err := json.Unmarshal(data, &raw); err != nil {\n\t\treturn err\n\t}\n\tmapData, ok := raw[\"path_rule_map\"]\n\tif !ok || len(mapData) == 0 || string(mapData) == \"null\" {\n\t\treturn nil\n\t}\n\n\t// Parse ordered keys using a streaming decoder.\n\tdec := json.NewDecoder(strings.NewReader(string(mapData)))\n\t// Read opening '{'\n\tt, err := dec.Token()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"expected '{' in path_rule_map: %w\", err)\n\t}\n\tif t != json.Delim('{') {\n\t\treturn fmt.Errorf(\"expected '{' in path_rule_map, got %v\", t)\n\t}\n\tfor dec.More() {\n\t\t// Read key\n\t\tkeyTok, err := dec.Token()\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"read path_rule_map key: %w\", err)\n\t\t}\n\t\tkey, ok := keyTok.(string)\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"expected string key in path_rule_map, got %T\", keyTok)\n\t\t}\n\t\t// Read value\n\t\tvar value string\n\t\tif err := dec.Decode(&value); err != nil {\n\t\t\treturn fmt.Errorf(\"read path_rule_map value for %q: %w\", key, err)","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/alibaba/open-code-review/blob/5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f/internal/config/rules/system_rules.go#L46-L82","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Validate the whole rules file with a JSON linter / 'jq .' before loading","Check the path_rule_map value specifically — it must be a complete {\"pattern\":\"rule\"} object","Fix truncation or stray characters around the path_rule_map block","If path_rule_map is optional, either omit the key or set it to null (both are handled) rather than an empty/broken value"],"exampleFix":"// before (truncated)\n\"path_rule_map\": {\"*.go\": \"golang\"\n// after\n\"path_rule_map\": {\"*.go\": \"golang.md\"}","handlingStrategy":"validation","validationCode":"func validRulesConfig(data []byte) error {\n    var probe map[string]json.RawMessage\n    if err := json.Unmarshal(data, &probe); err != nil { return err }\n    m, ok := probe[\"path_rule_map\"]\n    if !ok || string(m) == \"null\" { return nil }\n    var obj map[string]string\n    return json.Unmarshal(m, &obj) // catches truncated/broken objects early\n}","typeGuard":"func isPathRuleMap(v json.RawMessage) bool {\n    var obj map[string]string\n    return len(v) > 0 && string(v) != \"null\" && json.Unmarshal(v, &obj) == nil\n}","tryCatchPattern":"rule, err := rules.LoadDefault()\nif err != nil {\n    var dec *json.SyntaxError\n    if errors.As(err, &dec) {\n        return fmt.Errorf(\"malformed rules config at offset %d: %w\", dec.Offset, err)\n    }\n    return err\n}","preventionTips":["Run 'jq .' on custom rules files before shipping them","Never commit partially edited config; validate in CI","Keep path_rule_map as a complete JSON object or omit/null it","Lint configs after any generation step that writes them"],"tags":["config","json-parsing","rules"],"backgroundTag":"invalid-json-config","analyzedSha":"5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f","analyzedAt":"2026-09-02T02:08:09.116Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}