{"record":{"id":"6bf0108fe55601aa","repo":"ory/kratos","slug":"identity-schema-rejected-invalid-regex-in-pattern-6bf010","errorCode":null,"errorMessage":"identity schema rejected: invalid regex in patternProperties key %q: %w","messagePattern":"identity schema rejected: invalid regex in patternProperties key %q: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"schema/prevalidate.go","lineNumber":95,"sourceCode":"\t\t\tcase strings.HasPrefix(ref, \"#/\"):\n\t\t\t\tp.refs[path] = strings.TrimPrefix(ref, \"#\")\n\t\t\t}\n\t\t}\n\n\t\t// Pre-compile `pattern` regexes so an invalid one returns a\n\t\t// kratos-side error instead of panicking deep in\n\t\t// regexp.MustCompile during the upstream compile.\n\t\tif pat, ok := v[\"pattern\"].(string); ok {\n\t\t\tif _, err := regexp.Compile(pat); err != nil {\n\t\t\t\treturn fmt.Errorf(\"identity schema rejected: invalid regex in pattern: %w\", err)\n\t\t\t}\n\t\t}\n\n\t\t// patternProperties keys are themselves regexes.\n\t\tif patternProps, ok := v[\"patternProperties\"].(map[string]any); ok {\n\t\t\tfor raw := range patternProps {\n\t\t\t\tif _, err := regexp.Compile(raw); err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"identity schema rejected: invalid regex in patternProperties key %q: %w\", raw, err)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor k, sub := range v {\n\t\t\tif err := p.walk(sub, path+\"/\"+escapeJSONPointer(k)); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\n\tcase []any:\n\t\tfor i, sub := range v {\n\t\t\tif err := p.walk(sub, path+\"/\"+strconv.Itoa(i)); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n","sourceCodeStart":77,"sourceCodeEnd":113,"githubUrl":"https://github.com/ory/kratos/blob/b86338da04a040247a07f46100a86dcfb3875909/schema/prevalidate.go#L77-L113","documentation":"When walking an identity schema, preValidateSchema treats every key of a \"patternProperties\" object as a regular expression and pre-compiles it with Go's regexp. If a key does not compile as RE2, walk returns this error naming the offending key, preventing a later panic inside the upstream compiler.","triggerScenarios":"An identity schema contains \"patternProperties\" with a key that is not a valid Go RE2 regex — e.g. {\"(?<foo>bar)\": {...}}, {\"[a-\": {...}} (unclosed class), or a key with an unescaped literal '%' or stray metacharacter. Raised during pre-validation of the schema.","commonSituations":"Schemas authored for PCRE/ECMAScript regex dialects with RE2-unsupported features; hand-written patternProperties keys with typos; generated schemas where keys were interpolated from user data containing regex metacharacters.","solutions":["Fix the named patternProperties key (shown as %q in the error) so it is a valid Go RE2 regular expression.","Remove RE2-unsupported constructs (lookarounds, backreferences) from the key; use plain character classes or explicit alternation instead.","Escape literal metacharacters in keys that are meant to match literally.","Pre-compile all patternProperties keys with regexp.Compile in a test to catch invalid keys before submitting the schema."],"exampleFix":"// before\n\"patternProperties\": {\n  \"^([0-9]+\\1)$\": { \"type\": \"string\" }   // backreference, invalid in RE2\n}\n// after\n\"patternProperties\": {\n  \"^([0-9]+)$\": { \"type\": \"string\" }","handlingStrategy":"validation","validationCode":"for key := range schemaObj[\"patternProperties\"].(map[string]any) {\n    if _, err := regexp.Compile(key); err != nil {\n        return fmt.Errorf(\"patternProperties key %q invalid: %w\", key, err)\n    }\n}","typeGuard":null,"tryCatchPattern":"if strings.Contains(err.Error(), \"invalid regex in patternProperties key\") {\n    // extract key from message and fix that specific pattern\n}","preventionTips":["Treat patternProperties keys as regexes — lint them with regexp.Compile","Avoid ECMAScript/PCRE-flavored regexes in keys","Escape metacharacters intended to match literally"],"tags":["regex","jsonschema","identity-schema","pattern-properties"],"backgroundTag":"invalid-regex-pattern","analyzedSha":"b86338da04a040247a07f46100a86dcfb3875909","analyzedAt":"2026-09-07T15:58:15.934Z","contentChangedAt":"2026-09-07T15:58:15.934Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}