ory/kratos · error

identity schema rejected: invalid regex in pattern

Error message

identity schema rejected: invalid regex in pattern: %w

What it means

preValidateSchema walks an identity schema before handing it to the upstream JSON Schema compiler and pre-compiles every "pattern" value with Go's regexp. If a pattern is not a valid RE2 regular expression, walk returns this wrapped error instead of letting regexp.MustCompile panic deep inside the upstream compile.

Solutions

  1. Fix the "pattern" value in the identity schema so it compiles as a Go RE2 regular expression (regexp.Compile).
  2. Remove unsupported constructs: lookaheads/lookbehinds ((?=...), (?!...), (?<=...)) and backreferences are not valid in RE2 — restructure the pattern or validate those parts in application code instead.
  3. Test the regex locally with a small Go snippet (regexp.Compile) or an RE2-compatible tester before submitting the schema.
  4. Escape metacharacters that were meant literally (e.g. use \. for a literal dot) to fix 'missing closing )' or 'missing argument to repetition operator' errors.

Example fix

// before
"pattern": "^(?=.*[A-Z]).+$"   // lookahead, unsupported by RE2
// after
"pattern": "^[A-Za-z0-9]*[A-Z][A-Za-z0-9]*$"   // RE2-compatible equivalent
Defensive patterns

Strategy: validation

Validate before calling

func validatePattern(p string) error {
    if _, err := regexp.Compile(p); err != nil {
        return fmt.Errorf("pattern %q invalid: %w", p, err)
    }
    return nil
}

Try / catch

var re *syntax.Error
if errors.As(err, &re) {
    log.Printf("fix RE2 regex: %v (code=%v expr=%q)", re, re.Code, re.Expr)
}

Prevention

When it happens

Trigger: An identity schema JSON contains a "pattern" keyword whose string is not a valid Go RE2 regex, e.g. "(?<name>...)" (Go RE2 does not support lookbehind or certain group naming), unbalanced parentheses, or a trailing backslash. Raised during pre-validation of any identity schema submitted for compilation.

Common situations: Patterns copied from JavaScript/PCRE-flavored validators that use lookaheads ((?=...)) or backreferences, which Go's RE2 engine does not support; typos like unclosed character classes; patterns built dynamically from user input that contain regex metacharacters.

Related errors


AI-assisted analysis of ory/kratos@b86338da04 (2026-09-07). Data as JSON: /api/errors/a1e9e5fd9332bcc5. Report an issue: GitHub.

Appendix: source

Thrown at schema/prevalidate.go:87

		// Record `$ref` for cycle detection in detectRefCycles. Root
		// pointers (`#`, `#/`, empty) map to the empty path. Anything
		// without a `#/` prefix is external — out of scope here;
		// loadRefURL handles scheme enforcement.
		if ref, ok := v["$ref"].(string); ok {
			switch {
			case ref == "" || ref == "#" || ref == "#/":
				p.refs[path] = ""
			case strings.HasPrefix(ref, "#/"):
				p.refs[path] = strings.TrimPrefix(ref, "#")
			}
		}

		// Pre-compile `pattern` regexes so an invalid one returns a
		// kratos-side error instead of panicking deep in
		// regexp.MustCompile during the upstream compile.
		if pat, ok := v["pattern"].(string); ok {
			if _, err := regexp.Compile(pat); err != nil {
				return fmt.Errorf("identity schema rejected: invalid regex in pattern: %w", err)
			}
		}

		// patternProperties keys are themselves regexes.
		if patternProps, ok := v["patternProperties"].(map[string]any); ok {
			for raw := range patternProps {
				if _, err := regexp.Compile(raw); err != nil {
					return fmt.Errorf("identity schema rejected: invalid regex in patternProperties key %q: %w", raw, err)
				}
			}
		}

		for k, sub := range v {
			if err := p.walk(sub, path+"/"+escapeJSONPointer(k)); err != nil {
				return err
			}
		}

View on GitHub (pinned to b86338da04)