different-ai/openwork · error · InterpreterRuntimeError

String.${method} received the string ${JSON.stringify(arg)},

Error message

String.${method} received the string ${JSON.stringify(arg)}, which is not a valid regular expression pattern (${regexFailureReason(error)}). ${escapeRegexHint}

What it means

toHostRegex compiles string arguments into host RegExp for String methods like match/replace/split. When the pattern string fails to compile (invalid syntax such as unbalanced brackets or bad groups), the underlying SyntaxError is rethrown as this InterpreterRuntimeError — surfaced as a SyntaxError via .as() — including the original failure reason and a hint about escaping.

Source

Thrown at packages/codemode/src/stdlib/regexp.ts:27

  "multiline",
  "sticky",
  "unicode",
  "dotAll",
])

export const regexFailureReason = (error: unknown): string =>
  (error instanceof Error ? error.message : String(error)).replace(/^Invalid regular expression:\s*/i, "")

export const escapeRegexHint =
  'To match special characters like ( ) [ ] { } + * ? . literally, escape them with a backslash (e.g. "\\\\(") or test for them with String.includes instead.'

export const toHostRegex = (arg: unknown, method: string, node: AstNode, extraFlags = ""): RegExp => {
  if (arg instanceof SandboxRegExp) return arg.regex
  if (typeof arg === "string") {
    try {
      return new RegExp(arg, extraFlags)
    } catch (error) {
      throw new InterpreterRuntimeError(
        `String.${method} received the string ${JSON.stringify(arg)}, which is not a valid regular expression pattern (${regexFailureReason(error)}). ${escapeRegexHint}`,
        node,
      ).as("SyntaxError")
    }
  }
  throw new InterpreterRuntimeError(
    `String.${method} expects a regular expression (a /pattern/flags literal or new RegExp(...)) or a string pattern, not ${arg === null ? "null" : typeof arg}.`,
    node,
  )
}

export const matchToValue = (match: RegExpMatchArray): Array<unknown> => {
  const result: Array<unknown> = Array.from(match, (group) => group)
  if (match.index !== undefined) (result as Record<string, unknown> & Array<unknown>).index = match.index
  if (match.groups) {
    const groups: SafeObject = Object.create(null) as SafeObject
    for (const [key, group] of Object.entries(match.groups)) {
      if (!isBlockedMember(key)) groups[key] = group

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Escape dynamic input before embedding: use an escapeRegExp helper (replace /[.*+?^${}()|[\]\\]/g, '\\$&')
  2. Validate the pattern compiles in a plain JS try/catch with new RegExp(pattern) before running the CodeMode script
  3. Prefer literal strings with split/indexOf over regex when the pattern is data
  4. Fix hand-written regex syntax (balanced brackets, valid quantifiers) — the message names the exact failure reason

Example fix

// before
const parts = text.match('(' + userDelimiter + ')')
// after
const esc = userDelimiter.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
const parts = text.match('(' + esc + ')')
Defensive patterns

Strategy: try-catch

Validate before calling

function isValidRegex(pattern: string): boolean {
  try { new RegExp(pattern); return true } catch { return false }
}
if (!isValidRegex(pattern)) pattern = escapeRegExp(pattern)

Try / catch

try {
  return text.match(pattern)
} catch (e) {
  if (e instanceof InterpreterRuntimeError && e.message.includes('not a valid regular expression pattern')) {
    return text.split(escapeRegExp(pattern))[0] // or literal fallback
  }
  throw e
}

Prevention

When it happens

Trigger: String.match('['), String.replaceAll('a{2,1}', ...), patterns interpolated from user input like new RegExp('(' + userTag + ')') where userTag contains regex metacharacters, unescaped dots/brackets from data, or an empty/invalid group '()+' edge in dynamically built patterns.

Common situations: Building patterns from config values or user-supplied delimiters without escaping; log-parsing scripts where the delimiter contains regex specials like '(' or '['; LLM-generated code with hand-written regex typos.

Related errors


AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01). Data as JSON: /api/errors/ea867e024de6089c. Report an issue: GitHub.