Next.js and Node.js

@errorbird/nextjs sends a Next.js app's server errors, browser errors and the render errors caught by React error boundaries to Errorbird, and uploads source maps after the build. Setup is three files.

Errors are collected from three places:

Where With Example
Server instrumentation.ts → onRequestError Server Component, route handler, server action, proxy
Browser instrumentation-client.ts Error in an event handler, rejected promise
React error boundary error.tsx / global-error.tsx → useReportError Render error in a client component

Requires Next.js 15.3 or later (App Router). Server and browser errors land in the same project and are grouped by the same rules. For Node.js apps that do not use Next.js, see the section below.

Installation

npm install @errorbird/nextjs

Environment variables (.env or your hosting dashboard):

ERRORBIRD_SECRET_KEY=ebrd_secret_…          # server only
NEXT_PUBLIC_ERRORBIRD_KEY=ebrd_pub_…        # browser; publishable key
[email protected]     # e.g. commit SHA; source maps match on this name

The secret key's name must not start with NEXT_PUBLIC_: Next.js inlines every value with that prefix into the code sent to the browser. Add your site's address to the publishable key's allowed domains.

Server: instrumentation.ts

At the project root (or under src/):

import { captureRequestError, register as registerErrorbird } from '@errorbird/nextjs/server'

export function register() {
  registerErrorbird()
}

export const onRequestError = captureRequestError

That is enough to send every server error; the same code runs on the Node.js and Edge runtimes. Each event carries the route (/orders/[id]), the route type (render, route, action), the request method and the path.

Browser: instrumentation-client.ts

import { init } from '@errorbird/nextjs/client'

init({
  key: process.env.NEXT_PUBLIC_ERRORBIRD_KEY!,
  release: process.env.NEXT_PUBLIC_ERRORBIRD_RELEASE,
})

Next.js runs this file before React; navigations, clicks and network requests are recorded as the steps before an error. The options are the same as the browser SDK's.

Error boundaries: error.tsx and global-error.tsx

Render errors caught by React never reach the browser's global error event; send them from your error page:

'use client'
import { useReportError } from '@errorbird/nextjs/client'

export default function Error({ error, reset }: { error: Error & { digest?: string }; reset: () => void }) {
  useReportError(error)
  return <button onClick={reset}>Try again</button>
}

If the error happened on the server (error.digest is set), it is not sent again from the browser: the server already reported it through onRequestError, and the copy that reaches the browser has its message hidden. The digest code you show the user is stored in the event's digest tag, so you can search for it in the dashboard.

Source maps

To map browser errors back to your original code, in next.config.ts:

const nextConfig = {
  productionBrowserSourceMaps: true,
}

In your build pipeline, right after next build:

export NEXT_PUBLIC_ERRORBIRD_RELEASE="web@$(git rev-parse --short HEAD)"
npx next build
ERRORBIRD_SECRET_KEY="$ERRORBIRD_SECRET_KEY" npx errorbird-nextjs sourcemaps

The command uploads the maps under .next/static and then deletes them: Next.js serves that folder as is, and the maps contain your source code. Pass --keep to keep them. Both Turbopack (Next.js 16) and webpack output are supported; the command handles Turbopack naming a map differently from its file (40h_0x9t.js → 03ftdzq5.js.map).

The release must match. If NEXT_PUBLIC_ERRORBIRD_RELEASE at build time and the release used for the upload are not identical, nothing is mapped. Derive both from the same environment variable.

Server-side stack traces point to the compiled files (.next/server/…); Next.js does not minify server code by default, so the lines stay readable.

What is and is not sent

Use beforeSend to change or drop an event before it is sent, and ignoreErrors to skip specific errors.

Node.js (Express, NestJS…)

For servers that do not use Next.js, use @errorbird/node:

npm install @errorbird/node
import { init, captureException } from '@errorbird/node'

init({
  key: process.env.ERRORBIRD_SECRET_KEY!,
  release: process.env.ERRORBIRD_RELEASE,
  environment: 'production',
})

// Express: error middleware, after your routes
app.use((error, request, response, next) => {
  captureException(error, { url: request.path, method: request.method })
  next(error)
})

Uncaught errors are sent automatically. If the app has no uncaughtException listener of its own, Node's default behaviour is kept: the error is printed, the send is awaited and the process exits with code 1. The SDK does not listen to unhandledRejection; doing so would switch off Node's "a rejected promise ends the process" behaviour.

On serverless platforms (AWS Lambda, Vercel functions) call await flush() before returning the response; otherwise a pending send can be lost when the function is frozen.

Source maps for a compiled server (TypeScript, esbuild):

ERRORBIRD_SECRET_KEY=… npx errorbird-sourcemaps --release [email protected] --delete dist