Source mapsBeta

Upload source maps so minified stack traces can be read.

How it works

  1. Set release on the SDK, so every error says which build it came from. See Environments and releases.
  2. After each build, upload its source maps for that release.
  3. When you open the error’s entry on the Logs page, choose De-minify to see the stack trace mapped back to your source files.

Stack traces are stored as they arrived; mapping happens when you ask for it. Grouping and suspect commits use the stack as it arrived.

Upload a source map

POST
/api/v1/{projectId}/sourcemaps

X-API-Key required.

FieldRequiredWhat to send
releaseyesThe same string as the SDK’s release option, up to 100 characters.
originalFileNameyesThe JavaScript file’s name as it appears in stack traces, such as main.3f9a1c.js, or its full URL.
fileNameyesThe source map file’s name, such as main.3f9a1c.js.map.
sourceMapDatayesThe source map file’s contents, as a string.
uploadedBynoWho or what uploaded it.

Uploading again for the same release and file replaces the earlier map. With jq 1.6 or later, a single file looks like this:

Terminal
jq -n \
  --arg release "2.4.1" \
  --arg file "main.3f9a1c.js" \
  --rawfile map "dist/assets/main.3f9a1c.js.map" \
  '{release: $release, originalFileName: $file, fileName: ($file + ".map"), sourceMapData: $map}' \
| curl -fsS -X POST "https://apperioserver.onrender.com/api/v1/your-project-id/sourcemaps" \
    -H "X-API-Key: your-api-key" \
    -H "Content-Type: application/json" \
    --data @-

The response is 201:

JSON
{
  "status": "success",
  "message": "Source map uploaded successfully",
  "data": {
    "_id": "source-map-id",
    "projectId": "your-project-id",
    "release": "2.4.1",
    "fileName": "main.3f9a1c.js.map",
    "originalFileName": "main.3f9a1c.js",
    "fileSize": 12345,
    "createdAt": "2026-01-15T12:00:00.000Z",
    "updatedAt": "2026-01-15T12:00:00.000Z"
  }
}

Upload a whole build

A Node.js script you can run in CI after the build, with the key, project ID and release in environment variables:

scripts/upload-source-maps.ts
import { readdir, readFile } from 'node:fs/promises';
import path from 'node:path';

const dir = 'dist/assets';
const url = `https://apperioserver.onrender.com/api/v1/${process.env.APPERIO_PROJECT_ID}/sourcemaps`;

for (const name of await readdir(dir)) {
  if (!name.endsWith('.js.map')) continue;

  const response = await fetch(url, {
    method: 'POST',
    headers: {
      'X-API-Key': process.env.APPERIO_API_KEY ?? '',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      release: process.env.RELEASE,
      originalFileName: name.replace(/\.map$/, ''),
      fileName: name,
      sourceMapData: await readFile(path.join(dir, name), 'utf8'),
    }),
  });

  if (!response.ok) throw new Error(`${name}: upload failed with ${response.status}`);
  console.log(`Uploaded ${name}`);
}
Terminal
RELEASE=2.4.1 node scripts/upload-source-maps.ts

Node.js 22.18 and later run this TypeScript file directly. It has no type annotations, so on older versions rename it to .mjs.

Read a stack trace

On the Logs page, open an entry that has a stack trace and a release. Choose De-minify, then switch between Minified and Resolved. Frames without a matching map stay as they were.

Limits

  • Only stack traces in the Chrome, Edge and Node.js format (lines starting at) can be mapped. Firefox and Safari stacks stay minified.
  • A request body can be up to 5 MB, so very large maps can’t be uploaded yet.
  • Upload with the API. The Source Maps page in the dashboard isn’t connected to it yet.

Beta

Source maps work today but are still changing.