JavaScript Source Maps

When a browser error is captured via the OpenTelemetry Browser SDK, minified stack traces make it nearly impossible to diagnose the root cause. Uptrace resolves minified file names, line numbers, and function names back to original source locations using source maps — automatically.

How it works

  1. Your browser app sends an error span with telemetry.sdk.language = webjs.
  2. Uptrace extracts exception.stacktrace and parses it (Chrome and Firefox formats supported).
  3. For each stack frame, Uptrace resolves the original source location using a source map.
  4. The stack trace is rewritten with original file names, line numbers, column numbers, and function names.

Source maps are resolved in this order:

  1. Uploaded source maps — checked first. Matched by project, minified URL, service name, and service version.
  2. HTTP fetch — if no uploaded map matches, Uptrace fetches the minified JS file, looks for a //# sourceMappingURL= comment or SourceMap HTTP header, then fetches and parses the referenced map.

Resolved positions are cached for 6 hours. Failed lookups are cached for 1 hour to avoid repeated requests.

Configuration

Source map processing is enabled by default. For self-hosted Uptrace, see the configuration reference for cache tuning and upload API options.

Uploading source maps

Uptrace stores user-uploaded source maps and resolves them before attempting an HTTP fetch. Upload is enabled by default — set upload_disabled: true in your configuration to turn it off. Uploading is the recommended approach for production because it does not require Uptrace to have internet access and gives you full control over which maps are available.

If you report browser errors with the Sentry SDK, prefer uploading with a Sentry bundler plugin instead of the REST API below.

Upload a source map

bash
curl -X POST "https://<uptrace-host>/api/v1/sourcemaps" \
  -H "uptrace-dsn: https://<token>@<uptrace-host>/<project_id>" \
  -F "file=@dist/app.js.map" \
  -F "minified_url=https://example.com/static/app.js" \
  -F "service_name=frontend" \
  -F "service_version=1.2.3"

The upload endpoint authenticates with a project token (DSN) — the same DSN used to send telemetry data.

FieldRequiredDescription
fileyesThe source map JSON file.
minified_urlyesThe URL of the minified JS file as seen in error stack traces.
service_namenoService name to scope the map (matches service.name).
service_versionnoService version to scope the map (matches service.version).

If a source map with the same (project_id, minified_url, service_name, service_version) already exists, it is replaced.

List source maps

bash
curl "https://<uptrace-host>/api/v1/sourcemaps/<project_id>" \
  -H "Authorization: Bearer <user_token>"

Returns all uploaded source maps for the project. Requires a user token with edit permissions.

Delete a source map

bash
curl -X DELETE "https://<uptrace-host>/api/v1/sourcemaps/<project_id>/<sourcemap_id>" \
  -H "Authorization: Bearer <user_token>"

Limits

  • Maximum 200 source maps per project
  • Maximum 64 MB per upload
  • Source map must be valid JSON in source map v3 format

Uploading with Sentry bundler plugins

Uptrace also implements the Sentry chunk-upload and artifact-bundle protocol, so if you report browser errors with the Sentry SDK you can upload source maps with the standard Sentry bundler plugins — @sentry/vite-plugin, @sentry/webpack-plugin, @sentry/rollup-plugin, or @sentry/esbuild-plugin.

These plugins inject a unique debug ID into each minified file and its map, and the Sentry SDK reports that ID with every error, so Uptrace selects the exact map for the build that produced the error — no URL or version matching required.

Point the plugin's url at your Uptrace ingest base, set org to your numeric project ID, and use a user token with edit permission as the authToken. See Sentry → Uploading source maps for a full Vite example.

CI/CD integration

Upload source maps as part of your build pipeline after every release:

bash
#!/bin/bash
set -euo pipefail

UPTRACE_DSN="https://<token>@api.uptrace.dev/<project_id>"
SERVICE_NAME="frontend"
SERVICE_VERSION=$(git rev-parse --short HEAD)
DIST_DIR="dist/assets"

for map in "$DIST_DIR"/*.js.map; do
  js_file="${map%.map}"
  js_name=$(basename "$js_file")
  minified_url="https://example.com/assets/$js_name"

  echo "Uploading $map -> $minified_url"
  curl -s -X POST "https://api.uptrace.dev/api/v1/sourcemaps" \
    -H "uptrace-dsn: $UPTRACE_DSN" \
    -F "file=@$map" \
    -F "minified_url=$minified_url" \
    -F "service_name=$SERVICE_NAME" \
    -F "service_version=$SERVICE_VERSION"
done

Automatic HTTP fetching

When no uploaded source map matches, Uptrace attempts to fetch it over HTTP:

  1. Fetches the minified JS file URL from the stack frame.
  2. Looks for //# sourceMappingURL=<url> at the end of the file, or a SourceMap HTTP response header.
  3. Fetches the referenced source map (supports absolute URLs, relative URLs, and data:application/json;base64,... inline maps).
  4. Parses and caches the result.

Security: Uptrace blocks requests to private/localhost IP addresses to prevent SSRF. The maximum source map size for HTTP fetching is 48 MB.

This mode requires no setup — if your minified files are publicly accessible and include a sourceMappingURL reference, source maps work automatically.

Supported stack trace formats

Chrome:

text
TypeError: Cannot read property 'foo' of undefined
    at bar (https://example.com/static/app.js:1:2345)
    at baz (https://example.com/static/app.js:1:6789)

Firefox:

text
bar@https://example.com/static/app.js:1:2345
baz@https://example.com/static/app.js:1:6789

Troubleshooting

Stack traces are not resolved:

  • Verify sourcemaps.disabled is not true in your configuration.
  • Confirm spans have telemetry.sdk.language = webjs. This is set automatically by the OpenTelemetry Browser SDK.
  • Ensure exception.stacktrace is present on error spans.

Uploaded maps are not applied:

  • minified_url must exactly match the URL in the stack trace.
  • If using service_name or service_version, they must match the service.name and service.version resource attributes on the span.
  • Verify the upload succeeded by listing source maps for the project.

HTTP fetch is not working:

  • Uptrace must be able to reach the minified file URL from the server.
  • The minified file must contain //# sourceMappingURL= or serve a SourceMap header.
  • Private/localhost URLs are blocked for security.
  • Check Uptrace logs for fetch errors.