gatsbyjs/gatsby · error

nodeModel.findOne() does not support sorting. Use nodeModel.

Error message

nodeModel.findOne() does not support sorting. Use nodeModel.findAll({ query: { limit: 1 } }) instead.

What it means

nodeModel.findOne resolves exactly one node and intentionally does not support sorting, because honoring a sort order would force Gatsby to track a connection (ordered set) rather than a single node. If args.query.sort.fields is non-empty, findOne throws and directs callers to findAll with limit:1.

Source

Thrown at packages/gatsby/src/schema/node-model.js:379

   *
   * @param {*} args
   * @param {Object} args.query Query arguments (e.g. `filter`). Doesn't support `sort`, `limit`, `skip`.
   * @param {(string|GraphQLOutputType)} args.type Type
   * @param {PageDependencies} [pageDependencies]
   * @returns {Promise<Node>}
   * @example
   * // Get one node of type `MyType` by its title
   * const node = await findOne({
   *   type: `MyType`,
   *   query: { filter: { title: { eq: `My Title` } } },
   * })
   */
  async findOne(args, pageDependencies = {}) {
    const { query = {} } = args
    if (query.sort?.fields?.length > 0) {
      // If we support sorting and return the first node based on sorting
      // we'll have to always track connection not an individual node
      throw new Error(
        `nodeModel.findOne() does not support sorting. Use nodeModel.findAll({ query: { limit: 1 } }) instead.`
      )
    }
    const { gqlType, entries } = await this._query({
      ...args,
      query: { ...query, skip: 0, limit: 1, sort: undefined },
    })
    const result = Array.from(entries)
    const first = result[0] ?? null

    if (!first) {
      // Couldn't find matching node.
      //  This leads to a state where data tracking for this query gets empty.
      //  It means we will NEVER re-run this query on any data updates
      //  (even if a new node matching this query is added at some point).
      //  To workaround this, we have to add a connection tracking to re-run
      //  the query whenever any node of this type changes.
      pageDependencies.connectionType = gqlType.name

View on GitHub (pinned to 8b06340921)

Solutions

  1. Replace findOne with findAll({ type, query: { filter, sort, limit: 1 } }) and read the first edge.
  2. Drop the sort and select deterministically by filter (e.g. by id).
  3. If sorting is essential, fetch via findAll and sort the returned array yourself.

Example fix

// before
const node = await nodeModel.findOne({
  type: `Article`,
  query: { filter: { id: { eq } }, sort: { fields: [`publishedAt`], order: [`DESC`] } },
})
// after
const result = await nodeModel.findAll({
  type: `Article`,
  query: { filter: { id: { eq } }, sort: { fields: [`publishedAt`], order: [`DESC`] }, limit: 1 },
})
const node = result.entries[0] ?? null
Defensive patterns

Strategy: validation

Validate before calling

function findOneSafe(nodeModel, args) {
  if (args.query?.sort?.fields?.length > 0) {
    // findOne cannot sort; route to findAll
    return nodeModel.findAll({ ...args, query: { ...args.query, limit: 1 } })
      .then(r => r.entries[0] ?? null)
  }
  return nodeModel.findOne(args)
}

Type guard

function queryHasSort(query = {}) {
  return Array.isArray(query.sort?.fields) && query.sort.fields.length > 0
}

Prevention

When it happens

Trigger: Calling nodeModel.findOne({ type, query: { filter: {...}, sort: { fields: ['date'], order: ['DESC'] } } }) inside a resolver, gatsby-node createResolvers, or a custom field extension.

Common situations: Porting findAll logic into findOne; resolver authors wanting 'the most recent X' via findOne.

Related errors


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