denoland/deno · error · Error

Invalid RegExp pattern: ${raw}

Error message

Invalid RegExp pattern: ${raw}

What it means

Thrown by the value parser in cli/js/40_lint_selector.js when an attribute value starts with '/' (marking a RegExp literal) but no closing '/' exists (raw.lastIndexOf("/") === -1). Attribute values in selectors can be quoted strings, regexes written /pattern/flags, numbers, or bigints — a lone slash means an unterminated regex.

Source

Thrown at cli/js/40_lint_selector.js:406

  switch (raw) {
    case "true":
      return true;
    case "false":
      return false;
    case "null":
      return null;
    case "undefined":
      return undefined;
    default:
      if (raw.startsWith("'") && raw.endsWith("'")) {
        if (raw.length === 2) return "";
        return raw.slice(1, -1);
      } else if (raw.startsWith('"') && raw.endsWith('"')) {
        if (raw.length === 2) return "";
        return raw.slice(1, -1);
      } else if (raw.startsWith("/")) {
        const end = raw.lastIndexOf("/");
        if (end === -1) throw new Error(`Invalid RegExp pattern: ${raw}`);
        const pattern = raw.slice(1, end);
        const flags = end < raw.length - 1 ? raw.slice(end + 1) : undefined;
        return new RegExp(pattern, flags);
      } else if (NUMBER_REG.test(raw)) {
        return Number(raw);
      } else if (BIGINT_REG.test(raw)) {
        return BigInt(raw.slice(0, -1));
      }

      return raw;
  }
}

export const ELEM_NODE = 1;
export const RELATION_NODE = 2;
export const ATTR_EXISTS_NODE = 3;
export const ATTR_BIN_NODE = 4;
export const PSEUDO_NTH_CHILD = 5;

View on GitHub (pinned to 89f33cbef2)

Solutions

  1. Close the regex literal: [value=/^\d+$/]
  2. If the pattern contains '/', escape it as \/ inside the selector value

Example fix

// before
"Literal[value=/https://]"(node) {},

// after
"Literal[value=/https:\/\//]"(node) {},
Defensive patterns

Strategy: validation

Validate before calling

function regexValuesClosed(sel) {
  for (const m of sel.matchAll(/=\/(?:[^/\\]|\\.)*/g)) {
    const rest = sel.slice(m.index + m[0].length);
    if (!/^\//.test(rest)) return false; // no closing '/'
  }
  return true;
}

Prevention

When it happens

Trigger: A selector like "Literal[value=/foo]", "[regex=/]", or any [...] value beginning with '/' that is not terminated by a second '/'. Common when the regex itself contains a '/' that was not escaped, terminating the literal early or confusing the writer.

Common situations: Trying to match string literal values by a pattern, e.g. [value=/^\d+$/], and forgetting to close or escape slashes; converting a JS regex literal into a selector value and dropping the trailing slash.

Related errors


AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16). Data as JSON: /api/errors/6369f32e2fc043c1. Report an issue: GitHub.