gatsbyjs/gatsby · error · ExportIsNotAsyncError

BabelPluginRemoveGraphQLQueries: the "${exportName}" export

Error message

BabelPluginRemoveGraphQLQueries: the "${exportName}" export must be async when using it with graphql

What it means

Thrown by `ExportIsNotAsyncError` (index.ts:620) when the `config` export is a function declaration (`export function config()`) used together with a graphql tag, but the function is not declared `async`. Gatsby's compiler must await graphql results inside the config export, so async is mandatory. The error records `exportStart` for source mapping.

Source

Thrown at packages/babel-plugin-remove-graphql-queries/src/index.ts:620

        })
        tagsToRemoveImportsFrom.forEach(removeImport)
      },
    },
  }
}

function isWithinConfigExport(
  path: NodePath<TaggedTemplateExpression>
): boolean {
  const parentExport = path.findParent(parent =>
    parent.isExportNamedDeclaration()
  ) as NodePath<ExportNamedDeclaration> | null

  const declaration = parentExport?.node?.declaration

  if (isFunctionDeclaration(declaration) && declaration.id?.name === `config`) {
    if (!declaration.async) {
      throw new ExportIsNotAsyncError(`config`, declaration.loc?.start)
    }
    return true
  }
  if (
    isVariableDeclaration(declaration) &&
    isIdentifier(declaration.declarations[0]?.id) &&
    declaration.declarations[0]?.id?.name === `config`
  ) {
    const init = declaration.declarations[0]?.init
    if (!isFunction(init) || !init.async) {
      throw new ExportIsNotAsyncError(`config`, init?.loc?.start)
    }
    return true
  }
  return false
}

export {

View on GitHub (pinned to 8b06340921)

Solutions

  1. Add the `async` keyword: `export async function config() { ... }`.
  2. Ensure any graphql tag inside the config export is awaited if needed.

Example fix

// before
export function config() {
  const data = graphql`query { site { buildTime } }`
  return { ... }
}

// after
export async function config() {
  const data = graphql`query { site { buildTime } }`
  return { ... }
}
Defensive patterns

Strategy: validation

Validate before calling

function configExportIsAsyncFunction(declNode) {
  return declNode.type === 'FunctionDeclaration' && declNode.id?.name === 'config' && declNode.async === true
}

Type guard

function isAsyncFunctionDeclaration(node) {
  return node?.type === 'FunctionDeclaration' && node.async === true
}

Try / catch

try {
  isWithinConfigExport(path)
} catch (e) {
  if (e instanceof ExportIsNotAsyncError) { /* add `async` to the export */ }
}

Prevention

When it happens

Trigger: Writing `export function config() { const x = graphql`...`; return {...} }` without the `async` keyword on the function declaration.

Common situations: Adopting the new file-based config (gatsby-config.ts / `config` export with graphql data fetching) and forgetting to mark the export async; converting a synchronous config to one that queries graphql.

Related errors


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