can1357/oh-my-pi · error · OmpTypeError
invalid regular expression pattern ${JSON.stringify(opts.pat
Error message
invalid regular expression pattern ${JSON.stringify(opts.pattern)} What it means
When `tString` receives a `pattern` option it compiles it with `new RegExp(pattern)`. If the pattern is syntactically invalid (unbalanced parens, bad flags-embedded constructs, invalid quantifiers), the engine's throw is caught and rethrown as `invalid regular expression pattern <JSON>`.
Source
Thrown at packages/omptype/src/typebox.ts:214
return schema;
}
function checkFiniteOption(name: string, value: number | undefined): void {
if (value !== undefined && !Number.isFinite(value)) throw new OmpTypeError(`${name} must be finite`);
}
function tString(opts?: StringOpts): TString {
checkFiniteOption("minLength", opts?.minLength);
checkFiniteOption("maxLength", opts?.maxLength);
let schema = asRuntime<string>(type.raw(opts?.format === "url" || opts?.format === "uri" ? "string.url" : "string"));
if (opts?.minLength !== undefined) schema = schema.atLeastLength(opts.minLength);
if (opts?.maxLength !== undefined) schema = schema.atMostLength(opts.maxLength);
if (opts?.pattern !== undefined) {
let regex: RegExp;
try {
regex = new RegExp(opts.pattern);
} catch {
throw new OmpTypeError(`invalid regular expression pattern ${JSON.stringify(opts.pattern)}`);
}
schema = schema.narrow((value, ctx) => regex.test(value) || ctx.mustBe(`a string matching ${opts.pattern}`));
}
if (opts?.format !== undefined && opts.format !== "url" && opts.format !== "uri") {
const format = opts.format;
const valid = formatPredicate(format);
schema = schema.narrow((value, ctx) => valid(value) || ctx.mustBe(`a string in ${format} format`));
}
const result = applyMeta(schema, opts);
const keywords: Record<string, unknown> = {};
if (opts?.pattern !== undefined) keywords.pattern = opts.pattern;
if (opts?.format !== undefined) keywords.format = opts.format === "url" ? "uri" : opts.format;
return opts?.pattern !== undefined || opts?.format !== undefined ? withJsonSchemaKeywords(result, keywords) : result;
}
function formatPredicate(format: string): (value: string) => boolean {
switch (format) {
case "url":View on GitHub (pinned to 9690622007)
Solutions
- Fix the pattern so it is valid JavaScript RegExp syntax — test it in the console with `new RegExp(pattern)`.
- Pre-validate user-supplied patterns with try { new RegExp(p) } before passing them to tString and surface a friendly config error.
- Convert non-JS regex syntax (lookbehind differences, POSIX classes, `\p{...}` without the u flag) to JS-compatible equivalents.
Example fix
// before
tString({ pattern: config.regex }); // throws if config.regex is "("
// after
let re;
try { re = new RegExp(config.regex); } catch { throw new Error(`config.regex is not a valid pattern: ${config.regex}`); }
tString({ pattern: config.regex }); Defensive patterns
Strategy: validation
Validate before calling
function assertValidPattern(p: string): string {
try { new RegExp(p); return p; }
catch { throw new Error(`Not a valid JS RegExp: ${JSON.stringify(p)}`); }
}
// use: tString({ pattern: assertValidPattern(config.regex) }) Type guard
function isValidRegex(p: string): boolean {
try { new RegExp(p); return true; } catch { return false; }
} Try / catch
try {
const s = tString({ pattern: userPattern });
} catch (err) {
if (err instanceof Error && err.message.includes('invalid regular expression pattern')) {
throw new ConfigError(`Invalid regex in config: ${JSON.stringify(userPattern)}`);
}
throw err;
} Prevention
- Pre-validate any user/config-supplied regex with new RegExp before it reaches the schema.
- Convert patterns from other dialects (PCRE/grep) to JS syntax explicitly.
- Beware string-escaping: prefer template/raw sources so `\d` isn't collapsed before compilation.
When it happens
Trigger: `tString({ pattern: "(" })`, `tString({ pattern: "a{2,1}" })`, or any user-supplied regex string from config/CLI/API that is not a valid JS RegExp.
Common situations: Letting end users supply regex filters through config files or API payloads; regexes copied from other tools (e.g. sed/grep syntax, PCRE) that are invalid in JS; double-escaping mistakes when building patterns from strings (`"\\d"` vs `"\d"` in non-raw contexts).
Related errors
- ${name} must be finite
- multipleOf must be greater than zero
- invalid index signature pattern ${keyDefinition}
- Type.${operation} requires a schema created by Type.Object
- ${kind} length must be a nonnegative safe integer
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/77be2730987b6c35.
Report an issue: GitHub.