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

  1. Fix the pattern so it is valid JavaScript RegExp syntax — test it in the console with `new RegExp(pattern)`.
  2. Pre-validate user-supplied patterns with try { new RegExp(p) } before passing them to tString and surface a friendly config error.
  3. 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

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


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/77be2730987b6c35. Report an issue: GitHub.