Server-side errors

The tracking script catches errors in the browser. This catches the other half: exceptions thrown on your server, so a crashed API route or page shows up in JAMP instead of only in your host's logs.

Server errors are posted to a single authenticated endpoint. You authenticate with your site's source map key (a per-site secret, the same one used for source maps), so it is safe to run server-to-server. Errors land in the same place as your browser errors, grouped by cause, tagged Server, with the route and method (so a group reads like POST /api/checkout). Messages and stack traces are scrubbed of emails, tokens and long numbers before storage, exactly like client errors.

Next.js

Next.js calls onRequestError for every uncaught server error. Add an instrumentation.ts at your project root:

instrumentation.ts
export async function onRequestError(err, request) {
  await fetch('https://jamp.io/api/errors/server', {
    method: 'POST',
    headers: { 'content-type': 'application/json' },
    body: JSON.stringify({
      website_id: 'YOUR_SITE_ID',
      key: 'YOUR_SOURCE_MAP_KEY',
      message: err?.message ?? String(err),
      stack: err?.stack,
      error_type: err?.name,
      route: request?.path,
      method: request?.method,
      // optional: attribute to a deploy
      release: process.env.VERCEL_GIT_COMMIT_SHA?.slice(0, 7),
    }),
  }).catch(() => {});
}

Any other server

The endpoint is framework-agnostic. From an Express error handler, a worker, or anywhere you catch an exception, POST the same JSON:

POST https://jamp.io/api/errors/server
content-type: application/json

{
  "website_id": "YOUR_SITE_ID",
  "key": "YOUR_SOURCE_MAP_KEY",
  "message": "Cannot read properties of undefined (reading 'id')",
  "stack": "...",
  "error_type": "TypeError",
  "route": "/api/orders",
  "method": "POST"
}

Fields

  • website_id and key are required (key = your source map key).
  • message is required; stack, error_type, route, method and release are optional.
  • Errors group by error_type + normalised message + route, so the same crash collapses into one entry with a count.

Good to know

  • Wrap the call so it can never throw inside your error hook (the .catch(() => ) above).
  • Don't report errors thrown by the reporting call itself, or you can loop.
  • Server errors count as error events (free, like client errors) and show up via the API and the MCP jamp_get_error tool, so an agent can read the stack and the deploy it started in.