gatsbyjs/gatsby · critical
UNHANDLED REJECTION
Error message
UNHANDLED REJECTION
What it means
Top-level `process.on('unhandledRejection', ...)` handler installed by the gatsby CLI. Any Promise rejection that nothing else `.catch`es reaches here; the handler wraps non-Error reasons into Errors and calls `report.panic`, which logs structured output and exits nonzero. The message is a generic label; the real cause is the wrapped `reason`.
Source
Thrown at packages/gatsby-cli/src/index.ts:69
// report.stripIndent(`
// Node.js ${version} has reached End of Life status on 31 December, 2019.
// Gatsby will only actively support ${NEXT_MIN_NODE_VERSION} or higher and drop support for Node 8 soon.
// Please upgrade Node.js to a currently active LTS release: https://gatsby.dev/upgrading-node-js
// `)
// )
// }
process.on(`unhandledRejection`, reason => {
// This will exit the process in newer Node anyway so lets be consistent
// across versions and crash
// reason can be anything, it can be a message, an object, ANYTHING!
// we convert it to an error object so we don't crash on structured error validation
if (!(reason instanceof Error)) {
reason = new Error(util.format(reason))
}
report.panic(`UNHANDLED REJECTION`, reason as Error)
})
process.on(`uncaughtException`, error => {
report.panic(`UNHANDLED EXCEPTION`, error)
})
createCli(process.argv)
View on GitHub (pinned to 8b06340921)
Solutions
- Read the wrapped `reason`/stack in the panic output to locate the rejecting code.
- Add `.catch()` or wrap the `await` in try/catch at the call site identified by the stack.
- Ensure all async lifecycle exports (`createPages`, etc.) fully await their promises.
- Update plugins/themes whose unhandled rejections are the source.
Example fix
// before: unawaited rejection
exports.createPages = ({ graphql }) => {
graphql(`{ ... }`).then(d => buildPages(d)) // rejection unhandled
}
// after
exports.createPages = async ({ graphql, reporter }) => {
try {
const { data } = await graphql(`{ ... }`)
buildPages(data)
} catch (e) { reporter.error('createPages failed', e) }
} Defensive patterns
Strategy: try-catch
Validate before calling
// Ensure all async lifecycle exports await and catch
async function safeRun(fn) { try { await fn() } catch (e) { reporter.error(e) } } Try / catch
process.on('unhandledRejection', (reason) => {
const err = reason instanceof Error ? reason : new Error(String(reason))
reporter.panic('UNHANDLED REJECTION', err)
}) Prevention
- Always `await` promises in `gatsby-node`/`gatsby-config` lifecycle hooks.
- Add `.catch()` to fire-and-forget promises.
- Keep plugins updated so their internal rejections are handled.
When it happens
Trigger: An async operation anywhere in the gatsby process rejects and no `.catch()`/`try-await` handles it. Examples: an unawaited `graphql()` call in `gatsby-node`, a plugin's async hook that throws, a fetch/filesystem rejection during build.
Common situations: Plugin or theme bug surfacing an unhandled rejection; `gatsby-node`/`gatsby-config` async code missing await or try/catch; Node version differences where unhandled rejections abort by default; network errors in user code called from lifecycle hooks.
Related errors
- UNHANDLED EXCEPTION
- Unhandled rejection
- BabelPluginRemoveGraphQLQueries: the "${exportName}" export
- Something went wrong when trying to add the plugins to the p
- starter ${starterPath} doesn't exist
AI-assisted analysis of gatsbyjs/gatsby@8b06340921 (2026-08-13).
Data as JSON: /api/errors/59aea3828c1143ff.
Report an issue: GitHub.