gatsbyjs/gatsby · error

Collection page builder encountered an error parsing the fil

Error message

Collection page builder encountered an error parsing the filepath. To use collection paths the schema to follow is {Model.field__subfield}. The problematic part is: ${part}.

What it means

gatsby-plugin-page-creator supports file-system routing with collection segments like `{Model.field__subfield}` (e.g. src/pages/{Product.name}.js). is-valid-collection-path-implementation.ts parses each path part and extracts the Model (word before the first dot) and the field chain (everything after the first dot) via regex. If either capture yields zero matches, or the counts of captured models and fields do not match, the part is rejected with this error. It indicates structurally malformed collection syntax (missing model, missing field, unbalanced braces, or extra dots).

Source

Thrown at packages/gatsby-plugin-page-creator/src/is-valid-collection-path-implementation.ts:29

  filePath: string,
  reporter: Reporter
): boolean {
  const parts = filePath.split(sysPath.sep)
  let passing = false
  let errors = 0

  parts.forEach(part => {
    if (!part.includes(`{`) && !part.includes(`}`)) return

    const model = Array.from(part.matchAll(/\{([a-zA-Z_]\w*)./g)) // Search for word before first dot, e.g. Model
    const field = Array.from(part.matchAll(/.*?((?<=\w\.)[^}]*)}/g)) // Search for everything after the first dot, e.g. foo__bar (or in invalid case: foo.bar)
    try {
      if (
        model.length === 0 ||
        field.length === 0 ||
        model.length !== field.length
      ) {
        throw new Error(errorMessage(part))
      }

      const models = Array.from(model, m => m[1])
      const fields = Array.from(field, f => f[1])

      for (const m of models) {
        assert(m, /^[a-zA-Z_]\w*$/, errorMessage(part)) // Check that Model is https://spec.graphql.org/draft/#sec-Names
      }
      for (const f of fields) {
        assert(f, /^[a-zA-Z_][\w_()]*$/, errorMessage(part)) // Check that field is foo__bar__baz (and not foo.bar.baz) + https://spec.graphql.org/draft/#sec-Names
      }
    } catch (e) {
      reporter.panicOnBuild({
        id: prefixId(CODES.CollectionPath),
        context: {
          sourceMessage: e.message,
        },
        filePath: filePath,

View on GitHub (pinned to 8b06340921)

Solutions

  1. Rewrite the filename to the {Model.field} form using __ for nested fields, e.g. {Product.category__slug}.js.
  2. Ensure exactly one {Model.field} token per path segment; split multiple tokens across separate path segments.
  3. Remove any stray curly braces from filenames that are not meant to be collection markers.
  4. Confirm the Model name matches an existing Gatsby node type (e.g. Mdx, MarkdownRemark) and the field is a valid GraphQL field on that type.

Example fix

// before
src/pages/{Product.category.slug}.js // dots are illegal in the field part

// after
src/pages/{Product.category__slug}.js // __ separates subfields
Defensive patterns

Strategy: validation

Validate before calling

const COLLECTION_PART = /\{([a-zA-Z_]\w*)\.([^}]+)\}/;
function isValidCollectionPart(part) {
  if (!part.includes('{') && !part.includes('}')) return true;
  const models = Array.from(part.matchAll(/\{([a-zA-Z_]\w*)\./g));
  const fields = Array.from(part.matchAll(/.*?((?<=\w\.)[^}]*)}/g));
  return models.length > 0 && models.length === fields.length;
}

Type guard

function isCollectionPath(p) {
  return p.split('/').every(part => {
    if (!part.includes('{')) return true;
    const models = Array.from(part.matchAll(/\{([a-zA-Z_]\w*)\./g));
    const fields = Array.from(part.matchAll(/.*?((?<=\w\.)[^}]*)}/g));
    return models.length > 0 && models.length === fields.length &&
      models.every(m => /^[a-zA-Z_]\w*$/.test(m[1]));
  });
}

Prevention

When it happens

Trigger: A file under src/pages whose name contains `{...}` but breaks the schema: `{.field}` (no Model), `{Model.}` (no field), `{Model.field.subfield}` (dots instead of __), `{Model.}` (trailing dot), or two collection markers in one segment like `{A.x}{B.y}` producing mismatched model/field counts. Also triggered by stray braces in a filename like `foo{bar}.js`.

Common situations: Coming from Next.js dynamic routes (`[slug]`) and using dots instead of the Gatsby `__` separator; copy-pasting a GraphQL field path with dots into the filename; accidentally leaving a literal `{` in a filename; renaming a model field but not the file.

Related errors


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