Skip to content

Source maps

Without source maps, production stack traces point at minified bundles and investigations end in sourcemap_unresolved or unfixable_no_sourcemap. With them, the worker sees your original source. This guide covers the Vite plugin and CI.

vite.config.ts
import { opslaneSourceMapPlugin } from '@opslane/sdk/vite-plugin';
export default {
plugins: [
opslaneSourceMapPlugin({
endpoint: 'https://your-opslane-instance.example.com',
apiKey: process.env.OPSLANE_API_KEY!,
release: process.env.GIT_SHA, // or omit and set VITE_OPSLANE_RELEASE
}),
],
};

What it does during vite build (build-only; it never touches dev serving):

  1. Forces build.sourcemap: 'hidden' — maps are generated but not referenced from the bundles.
  2. Collects every .map asset and removes it from the output bundle, so maps are never deployed to your CDN or exposed to users.
  3. After the bundle closes, uploads each map to POST /api/v1/sourcemaps with your API key and the release identifier.

The plugin refuses to upload without a release — a map filed under the wrong release is worse than no map. Resolution order:

  1. release plugin option, else
  2. VITE_OPSLANE_RELEASE environment variable, else
  3. warn loudly and skip the upload.

The value must be byte-identical to what your app passes to init({ release }). Using the git SHA for both is the reliable pattern; the install guide shows the per-framework env vars.

Source maps should upload from CI, where the release is unambiguous:

# e.g. GitHub Actions
- run: npm run build
env:
OPSLANE_API_KEY: ${{ secrets.OPSLANE_API_KEY }}
VITE_OPSLANE_API_KEY: ${{ secrets.OPSLANE_API_KEY }}
VITE_OPSLANE_RELEASE: ${{ github.sha }}

The sourcemap upload endpoint is authenticated by API key but not origin-gated (unlike browser endpoints), precisely so build machines can call it.

Verify the upload itself first — each accepted map returns HTTP 201 with its storage key:

{"status": "uploaded", "object_key": "sourcemaps/<project>/<release>/index-abc123.js.map"}

and is recorded in the source_maps table (self-host: SELECT release, filename FROM source_maps ORDER BY uploaded_at DESC LIMIT 5;).

Then verify end-to-end by triggering a test error from the built app: with maps in place for the matching release, investigations proceed against your original source instead of ending in needs_human with sourcemap_unresolved / unfixable_no_sourcemap. (Resolved frames are used inside the investigation; the incident view does not currently display a resolved stack, so the absence of those reason codes — and a sensible root-cause writeup referencing your real files — is the observable signal.) If you do hit sourcemap_unresolved, the release strings don’t match — compare what the SDK sent (release in the event payload) with what CI uploaded.

Only Vite has a first-party plugin today. From any other build, POST each map yourself:

Terminal window
curl -X POST "$OPSLANE_ENDPOINT/api/v1/sourcemaps" \
-H "X-API-Key: $OPSLANE_API_KEY" \
-F "release=$GIT_SHA" \
-F "file=@dist/assets/index-abc123.js.map"