vercel/next.js · critical · ExportError

NEXT_EXPORT_ERROR

NEXT_EXPORT_ERROR

Error message

Could not find a production build in the '${distDir}' directory. Try building your app with 'next build' before starting the static export. https://nextjs.org/docs/messages/next-export-no-build-id

What it means

At export/index.ts:237-243 the static exporter checks for `${distDir}/BUILD_ID`. If the file does not exist, it throws this `ExportError` (`code: NEXT_EXPORT_ERROR`). The export step (`next export`) operates on a completed production build, so a missing BUILD_ID means `next build` was never run (or ran into a different `distDir`).

Source

Thrown at packages/next/src/export/index.ts:240

        hasNowJson: !!(await findUp('now.json', { cwd: dir })),
        isCustomServer: null,
        turboFlag: options.bundler === Bundler.Turbopack,
        pagesDir: null,
        appDir: null,
      })
    )
  }

  const subFolders = nextConfig.trailingSlash && !options.buildExport

  if (!options.silent && !options.buildExport) {
    Log.info(`using build directory: ${distDir}`)
  }

  const buildIdFile = join(distDir, BUILD_ID_FILE)

  if (!existsSync(buildIdFile)) {
    throw new ExportError(
      `Could not find a production build in the '${distDir}' directory. Try building your app with 'next build' before starting the static export. https://nextjs.org/docs/messages/next-export-no-build-id`
    )
  }

  const customRoutes = (['rewrites', 'redirects', 'headers'] as const).filter(
    (config) => typeof nextConfig[config] === 'function'
  )

  if (!hasNextSupport && !options.buildExport && customRoutes.length > 0) {
    Log.warn(
      `rewrites, redirects, and headers are not applied when exporting your application, detected (${customRoutes.join(
        ', '
      )}). See more info here: https://nextjs.org/docs/messages/export-no-custom-routes`
    )
  }

  const buildId = await fs.readFile(buildIdFile, 'utf8')

View on GitHub (pinned to 0ae8c72462)

Solutions

  1. Run `next build` before `next export` (or use `output: 'export'` in config so build produces the export directly).
  2. Confirm `distDir` in next.config.js matches the directory export is reading.
  3. Ensure the build step succeeded and `.next/BUILD_ID` exists before invoking export.

Example fix

// before — running export without build
next export

// after — build first, or use output: 'export'
next build && next export
// OR next.config.js
module.exports = { output: 'export' } // `next build` then emits static output
Defensive patterns

Strategy: validation

Validate before calling

const fs = require('fs')
const path = require('path')
const distDir = '.next' // or read from config
if (!fs.existsSync(path.join(distDir, 'BUILD_ID'))) {
  throw new Error('Run `next build` before exporting')
}

Prevention

When it happens

Trigger: Running `next export` without a prior successful `next build`; the build wrote to a different `distDir` than export reads; the `.next` directory was deleted or not deployed; `distDir` was customized in config but the export runs against the default.

Common situations: CI pipeline that runs `next export` without `next build`; a clean step that wiped `.next`; renaming `distDir` in config; running export in a fresh checkout.

Related errors


AI-assisted analysis of vercel/next.js@0ae8c72462 (2026-08-06). Data as JSON: /api/errors/215454e340fd4b19. Report an issue: GitHub.