JavaScript Source Maps

Uptrace can resolve minified JavaScript stack traces back to original source code using source maps. When a browser error is captured via the OpenTelemetry Browser SDK, Uptrace parses the exception.stacktrace attribute, applies source maps, and replaces minified file/line/column references with the original source locations.

How it works

  1. Your browser app sends an error span with telemetry.sdk.language = webjs.
  2. Uptrace extracts the exception.stacktrace attribute and parses it (Chrome and Firefox formats).
  3. For each stack frame, Uptrace resolves the original source location using a source map.
  4. The stack trace is updated 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 source 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 all available options including cache tuning and enabling the upload API.

Uploading source maps

When upload_enabled: true in the configuration, you can upload source maps via the REST API. This is the recommended approach for production deployments because it does not require Uptrace to have internet access and gives you full control over which maps are available.

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. You can find it in your project settings.

FieldRequiredDescription
fileyesThe source map JSON file.
minified_urlyesThe URL of the minified JavaScript file as seen in errors.
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 (without the map data itself). This endpoint 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>"

Requires a user token with edit permissions.

Limits

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

Integrating with your build

Upload source maps as part of your CI/CD pipeline after every build. Here is an example using a shell script:

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.

Stack trace formats

Uptrace parses both Chrome and Firefox 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

After source map resolution, the stack trace is rewritten with original file names, line numbers, and function names.

Troubleshooting

Stack traces are not resolved:

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

Uploaded maps are not applied:

  • The minified_url must exactly match the URL in the stack trace.
  • If using service_name or service_version, these 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.