{"record":{"id":"0e8d7f62ff3a37b0","repo":"larksuite/cli","slug":"compile-rule-q-pattern-w","errorCode":null,"errorMessage":"compile rule %q pattern: %w","messagePattern":"compile rule %q pattern: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/security/contentsafety/config.go","lineNumber":49,"sourceCode":"\tID      string `json:\"id\"`\n\tPattern string `json:\"pattern\"`\n}\n\nfunc LoadConfig(configDir string) (*Config, error) {\n\tpath := filepath.Join(configDir, configFileName)\n\tdata, err := vfs.ReadFile(path)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"read content-safety config: %w\", err)\n\t}\n\tvar raw rawConfig\n\tif err := json.Unmarshal(data, &raw); err != nil {\n\t\treturn nil, fmt.Errorf(\"parse content-safety config: %w\", err)\n\t}\n\trules := make([]rule, 0, len(raw.Rules))\n\tfor _, r := range raw.Rules {\n\t\tcompiled, err := regexp.Compile(r.Pattern)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"compile rule %q pattern: %w\", r.ID, err)\n\t\t}\n\t\trules = append(rules, rule{ID: r.ID, Pattern: compiled})\n\t}\n\treturn &Config{Allowlist: raw.Allowlist, Rules: rules}, nil\n}\n\nfunc EnsureDefaultConfig(configDir string, errOut io.Writer) error {\n\tpath := filepath.Join(configDir, configFileName)\n\tif _, err := vfs.Stat(path); err == nil {\n\t\treturn nil\n\t}\n\tif err := vfs.MkdirAll(configDir, 0700); err != nil {\n\t\treturn fmt.Errorf(\"create config dir: %w\", err)\n\t}\n\tdata, err := json.MarshalIndent(defaultRawConfig(), \"\", \"  \")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"marshal default config: %w\", err)\n\t}","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/security/contentsafety/config.go#L31-L67","documentation":"LoadConfig compiles each rule's Pattern as a Go regexp after parsing. If regexp.Compile fails, the error names the rule ID whose pattern is invalid. Go RE2 syntax differs from PCRE/JavaScript regex, so patterns valid elsewhere may fail here.","triggerScenarios":"A rule in the content-safety config has a pattern with invalid RE2 syntax — e.g. unsupported constructs like lookbehind (?<=...), backreferences \\1, or unbalanced parentheses/brackets.","commonSituations":"Copying regex from PCRE/JS sources with lookarounds or backreferences; hand-editing patterns and leaving an unescaped '(' or '['; patterns written for a different regex flavor.","solutions":["Check the rule ID in the message and test the pattern with Go RE2 (e.g. https://regex101.com with the Go flavor)","Rewrite lookarounds/backreferences using RE2-supported constructs or match broader and filter in code","Escape unbalanced special characters ( ( [ ) properly","Validate patterns before shipping by compiling them in a test"],"exampleFix":"// before\n{\"id\": \"ssn\", \"pattern\": \"(?<=\\bseq)\\d{9}\"}  // lookbehind unsupported\n// after\n{\"id\": \"ssn\", \"pattern\": \"\\b\\d{3}-\\d{2}-\\d{4}\\b}\"}","handlingStrategy":"validation","validationCode":"for _, r := range rules {\n\tif _, err := regexp.Compile(r.Pattern); err != nil {\n\t\treturn fmt.Errorf(\"rule %q: invalid pattern: %w\", r.ID, err)\n\t}\n}","typeGuard":null,"tryCatchPattern":"config, err := contentsafety.LoadConfig(dir)\nif err != nil {\n\tif strings.Contains(err.Error(), \"compile rule\") {\n\t\t// extract rule ID from message, fix or drop that rule in the config, retry\n\t}\n\treturn err\n}","preventionTips":["Author patterns in RE2/Go flavor (no lookbehind, no backreferences)","Test every new pattern with regexp.Compile before committing it to config","Use regex101 with the Go (RE2) flavor when porting PCRE/JS regexes"],"tags":["config","regex","content-safety"],"backgroundTag":"invalid-regex-pattern","analyzedSha":"7fd6ef3c07182257ce776cdc5a614e122d5bd4b3","analyzedAt":"2026-09-04T21:17:44.649Z","contentChangedAt":"2026-09-04T21:17:44.649Z","schemaVersion":2},"datasetVersion":"2026-09-12T02:17:10.037Z"}