gatsbyjs/gatsby · error

The $regex comparator is expecting the regex as a string, no

Error message

The $regex comparator is expecting the regex as a string, not an actual regex or anything else

What it means

Gatsby's GraphQL `filter: { field: { regex: ... } }` operator expects the pattern as a string (Gatsby then compiles it to a `RegExp` via `prepareRegex`). Passing an actual `RegExp` object, a number, or any non-string is rejected because the value must be JSON-serialisable and transport-stable.

Source

Thrown at packages/gatsby/src/datastore/common/query.ts:190

 *
 * Example:
 *   { foo: { eq: 5 } } -> { foo: { $eq: 5 }}
 */
export function prepareQueryArgs(
  filterFields: Array<IInputQuery> | IInputQuery = {}
): IPreparedQueryArg {
  const filters = {}
  Object.keys(filterFields).forEach(key => {
    const value = filterFields[key]
    if (_.isPlainObject(value)) {
      filters[key === `elemMatch` ? `$elemMatch` : key] = prepareQueryArgs(
        value as IInputQuery
      )
    } else {
      switch (key) {
        case `regex`:
          if (typeof value !== `string`) {
            throw new Error(
              `The $regex comparator is expecting the regex as a string, not an actual regex or anything else`
            )
          }
          filters[`$regex`] = prepareRegex(value)
          break
        case `glob`:
          filters[`$regex`] = makeRe(value)
          break
        default:
          filters[`$${key}`] = value
      }
    }
  })
  return filters
}

// Converts a nested mongo args object into a dotted notation. acc
// (accumulator) must be a reference to an empty object. The converted

View on GitHub (pinned to 8b06340921)

Solutions

  1. Provide the pattern as a string, e.g. `regex: "/foo/i"`.
  2. Put flags inside the string (leading `/.../flags`) per Gatsby's `prepareRegex` convention.
  3. If building queries programmatically, ensure the value is `String(pattern)`.

Example fix

// before
allX(filter: { title: { regex: /foo/i } })
// after
allX(filter: { title: { regex: "/foo/i" } })
Defensive patterns

Strategy: type-guard

Validate before calling

// Before building the query string, coerce regex filter values.
function normalizeRegexFilter(value) {
  if (value instanceof RegExp) return value.toString() // "/pat/flags"
  if (typeof value !== "string") throw new Error("regex filter must be a string")
  return value
}

Type guard

function isRegexFilterValue(v: unknown): v is string {
  return typeof v === "string"
}

Prevention

When it happens

Trigger: Query like `allMarkdownRemark(filter: { frontmatter: { title: { regex: /foo/i } } })` (a literal regex object) or a programmatic query that injects an `RegExp`.

Common situations: Writing filter values in source that look like JS regex literals; passing variables whose value is a `RegExp`; migrating from a client library that accepts `RegExp`.

Related errors


AI-assisted analysis of gatsbyjs/gatsby@8b06340921 (2026-08-13). Data as JSON: /api/errors/3bd0c4ded124cdf0. Report an issue: GitHub.