Skip to Content
UsageSource Maps

Source Maps

Source maps let Rustrak translate minified JavaScript stack traces into their original source locations. When source maps are uploaded, errors show the real file name, line number, and source code — not the minified bundle.

Before and after

Without source maps:

Error: {"type":"Unknown","message":"Unknown Error"} 04 ? app:///_next/server/chunks/ssr/_0bwf~zv._.js:2:239718 03 ? app:///_next/server/chunks/ssr/apps_myapp_src_lib_actions_invoices_ts_09hq4k7._.js:2:5956 02 process.processTicksAndRejections node:internal/process/task_queues:103:5 01 Module.k [as generateMetadata] app:///_next/server/chunks/ssr/[root-of-the-server]__0fitma~._.js:2:5672

With source maps:

Error: Invoice not found 04 getPostedInvoice src/lib/actions/invoices.ts:84 03 fetchInvoiceData src/app/invoices/[id]/page.tsx:31 02 process.processTicksAndRejections node:internal/process/task_queues:103:5 01 generateMetadata src/app/invoices/[id]/page.tsx:12

Same error. One is debuggable, the other isn’t.

How to enable source maps

Source maps are uploaded automatically by the Sentry JavaScript SDK when you use the sourceMapsPlugin (or the Vite/webpack equivalent). No changes to your error tracking code are needed.

Vite

// vite.config.js import { defineConfig } from 'vite'; import { sentryVitePlugin } from '@sentry/vite-plugin'; export default defineConfig({ build: { sourcemap: true, // required }, plugins: [ sentryVitePlugin({ org: 'anything', // any value works, Rustrak ignores it project: 'my-project', // must match your Rustrak project slug authToken: 'your-api-token', url: 'http://localhost:8080', // your Rustrak server URL }), ], });

webpack

// webpack.config.js const { sentryWebpackPlugin } = require('@sentry/webpack-plugin'); module.exports = { devtool: 'source-map', // required plugins: [ sentryWebpackPlugin({ org: 'anything', project: 'my-project', authToken: 'your-api-token', url: 'http://localhost:8080', }), ], };

SvelteKit

@sentry/sveltekit wraps the Vite plugin, but names the server URL option sentryUrl, not url, and the options go at the root level:

// vite.config.js import { sentrySvelteKit } from '@sentry/sveltekit'; import { sveltekit } from '@sveltejs/kit/vite'; import { defineConfig, loadEnv } from 'vite'; export default defineConfig(({ mode }) => { // Vite does NOT populate process.env in config files, see note below const env = loadEnv(mode, process.cwd(), ''); return { plugins: [ sentrySvelteKit({ org: 'anything', // ignored by Rustrak project: 'my-project', // must match your Rustrak project slug authToken: env.SENTRY_AUTH_TOKEN, sentryUrl: 'http://localhost:8080', // NOT `url` in this SDK }), sveltekit(), ], }; });

Older examples nest these under sourceMapsUploadOptions: { ... }. That whole object is deprecated as of @sentry/sveltekit v10. Move the options to the root level, and rename url to sentryUrl while you’re there.

Vite does not load .env files into process.env when evaluating vite.config.js. If you set SENTRY_AUTH_TOKEN in a .env and read it via process.env, you’ll get undefined and the upload is silently skipped. Either use Vite’s loadEnv helper as shown above, or put the values in a .env.sentry-build-plugin file, which the Sentry plugin reads automatically from the current working directory.

Source maps are only uploaded during production builds (vite build), never in vite dev.

What org and project mean in Rustrak

OptionEnv varDoes Rustrak care?
orgSENTRY_ORGNo. Any non-empty string works.
projectSENTRY_PROJECTYes. Must match an existing Rustrak project’s slug (or its numeric ID).
url (sentryUrl in framework SDKs)SENTRY_URLYes. Must point at your Rustrak server.
authTokenSENTRY_AUTH_TOKENYes. A Rustrak API token from Settings → API Tokens.

Why org is ignored

Rustrak has no organizations, and this is by design rather than a missing feature.

In Sentry, an organization separates different customers sharing one server. It groups projects, users, and billing, and it decides which uploaded files each customer is allowed to see. Rustrak is self-hosted: everything on the server is already yours, so there is nothing to separate.

The error reporting protocol never sends an organization either. Your DSN is key@host/project_id, with no organization in it. So the project, not the organization, is what identifies your data.

The reason the option exists at all is that sentry-cli checks that the organization exists before it starts uploading. Rustrak answers that check with whatever slug you sent, and the upload proceeds. Set it to anything you like, or leave it as your company name so the config reads sensibly.

Why project is not ignored

The upload happens in two parts, and only the second one looks at your project. The files themselves are uploaded first, and that step succeeds no matter what project says. The final step attaches those files to a project, and that is where a wrong value fails with 404 project not found.

The build does not fail when this happens, so the only symptom is that your stack traces stay minified. See the troubleshooting section below.

Every option can be set through its environment variable instead of the config file; the explicit option wins when both are present.

The url must point to Rustrak. Source map upload is a separate channel from error reporting: your DSN controls where events go, but the build plugin decides where source maps go. If you leave url unset, the plugin uploads to Sentry’s hosted service (sentry.io) by default — pointing the DSN at Rustrak does not change this. And if authToken is missing, the upload is silently skipped and the build still succeeds. Other SDKs use the same two options under different names (e.g. sentryUrl for @sentry/nextjs, --url for sentry-cli).

How the upload works

The SDK uploads source maps in three steps during your build:

  1. Capability check — The SDK asks the server what chunk sizes it accepts.
  2. Chunk upload — Source map files are split into chunks and uploaded. Each chunk is keyed by its SHA-1 hash (content-addressable storage).
  3. Assembly — The SDK tells the server which chunks form a complete artifact bundle. The server assembles the ZIP and confirms.

From your perspective: run vite build (or webpack) and it happens automatically.

Because the upload runs during the build, the credentials (authToken / url) have to be available at build time. If you build in Docker or CI, pass the token to the build itself — a variable set only on the running container comes too late, and the upload is silently skipped.

Storage

Source map chunks are stored on disk in SOURCEMAP_STORAGE_PATH (default: /data/sourcemaps).

Sizing estimate: Each source map chunk is ~2MB. A typical app with 50 source files uses ~100MB. Scale as needed.

Set a persistent path for production:

SOURCEMAP_STORAGE_PATH=/var/lib/rustrak/sourcemaps

Make sure the directory is writable by the Rustrak process.

Production: shared volume required

If you run multiple Rustrak instances behind a load balancer, all instances must share the same SOURCEMAP_STORAGE_PATH. Chunks uploaded to one instance need to be readable by any other instance.

Mount a shared network volume (NFS, AWS EFS, etc.) and set the same SOURCEMAP_STORAGE_PATH on every instance:

# docker-compose.yml (multi-server example) services: rustrak: image: rustrak/rustrak-server:latest volumes: - sourcemaps_nfs:/var/lib/rustrak/sourcemaps environment: - SOURCEMAP_STORAGE_PATH=/var/lib/rustrak/sourcemaps

Single-server deployments don’t need to worry about this.

Troubleshooting: stack trace is still minified

Work through this checklist:

1. Is sourcemap: true (or devtool: 'source-map') enabled in your build config?

The SDK plugin can only upload source maps that your bundler actually generates. Check your build output for .map files.

2. Did the upload succeed during the build?

The plugin logs upload progress. Look for output like:

[sentry] Uploading source maps... [sentry] Artifact bundle assembled successfully
  • No upload output at all → the upload was skipped, almost always because authToken is missing. The build still succeeds, so this is easy to miss.
  • It uploaded, but errors are still minified → check url. If it isn’t set, source maps go to sentry.io by default, not to Rustrak. The DSN does not control this.
  • 404 project not found during assembly → your project / SENTRY_PROJECT doesn’t match any Rustrak project. Chunks upload fine (that step ignores the project), then the final assembly step rejects them. Use the exact project slug shown in the dashboard URL. Note that org is not the problem here, since Rustrak ignores it entirely.

Confirm what actually landed on the server:

# the `anything` segment is the org, which Rustrak ignores curl -H "Authorization: Bearer YOUR_TOKEN" \ http://localhost:8080/api/0/projects/anything/my-project/files/source-maps/

An empty data array means no source maps were ever uploaded for that project.

3. Is SOURCEMAP_STORAGE_PATH writable and persistent?

The default path (/data/sourcemaps) is cleared on restart on some systems. Set a persistent path in production.

4. Are debug_meta entries present in the event?

The Sentry SDK attaches debug_meta.images to each event, linking stack frames to the correct source map via a debug_id. If your SDK version doesn’t emit debug_meta, source map lookup won’t work. Use @sentry/browser 7.x or later.

5. Multi-server deployment: are all instances using a shared volume?

If chunks were uploaded to instance A but the event was processed by instance B, the source map won’t be found. See the shared volume section above.

Last updated on