OpenTelemetry

app.min.js:1:63
tells you nothing.

Minified bundles reduce every production error to single letters on line one. TracePath resolves each frame back to the file, line, and function you wrote, the moment the error arrives.

Open source · Pure Go · OpenTelemetry compatible

What the client sends

Error: user has no name
n()
app.min.js:1:63
t()
app.min.js:1:129
app.min.js:1:146
app.min.js:1:164

What TracePath shows you

Error: user has no name
validateUser../src/user.ts:8:11
handleSignup../src/index.ts:4:10
<anonymous>../src/index.ts:7:1
<anonymous>../src/index.ts:7:29
JavaScript
Remix
Node
Svelte
Next.js
React
Languages & throughput

JavaScript, Dart, Flutter, Swift, and Android.

One engine reads JavaScript source maps, Dart and Flutter obfuscation maps, iOS and Swift dSYM debug symbols, and Android R8 mapping files through the same compiled cache, plus every JS framework that ships them, from React and Svelte to Next.js and Remix. Even on the cheapest box we tested, a 2 vCPU Hetzner ccx13, it clears over 32× the stack traces per second of Honeycomb’s symbolicator.*

* Measured running as an OpenTelemetry Collector. The full benchmark workflow lives in the repo.

Performance

Symbolication that keeps up with ingest.

Most symbolicators re-parse source maps on every restart and hold them in RAM until the process dies. Ours compiles each map once, then memory-maps it from disk. The numbers below come straight from the benchmark workflow in the repo, run head to head against Honeycomb’s symbolicator on Hetzner hardware. Read why the design is this efficient →

30K+
Stacks/s, hot or cold
32×
Honeycomb's throughput under churn
18ms
Churn p99, where Honeycomb hits ~3s
361MB
Peak under churn, vs 4.5 GB
OpenTelemetry

Bring your own pipeline.

The same engine ships as an OpenTelemetry Collector processor. It’s a drop-in replacement for Honeycomb’s source_map_symbolicator: same component type, same attribute contract, same config keys. Existing pipelines and web instrumentation work unchanged.

  • Symbolicates spans, span events, and log records
  • Cache bounded by disk size, not an entry count in RAM
  • Pure Go, so no glibc base image required
  • Works in any collector build, with or without TracePath behind it
# compile the processor into your collector (ocb manifest)
processors:
  - gomod: github.com/tracepathhq/tracepath/backend v1.8.0
    import: github.com/tracepathhq/tracepath/backend/app/symbolicator/otelprocessor

$ ocb --config builder-config.yaml
Built in the open

Read the parser. Run the benchmarks. Self-host all of it.

The symbolicator, the benchmark harnesses, and the rest of TracePath live in one MIT-licensed repo. Nothing about how your stack traces get resolved is a black box.

VitewebpackesbuildRollupMetroNext.jsSvelteKitCloudflare Workers

Stop debugging app.min.js.

Upload your source maps once. Every production error after that points at the code you wrote.

FAQ

Questions about symbolication

What is stack trace symbolication?

Production JavaScript ships minified, so browsers report errors as positions in the bundle, like app.min.js:1:63 inside a function called n. Symbolication uses the source maps from your build to translate those frames back to the original file, line, column, and function name.

How do source maps get into TracePath?

Run npx tracepath-sourcemaps --directory ./dist after your build, in CI or locally. It uploads every .map file and its sibling bundle. Under the hood it's a single multipart HTTP endpoint, so plain curl works from any pipeline. Uploads authenticate with a per-project token you can revoke.

Does it work with OpenTelemetry?

Yes, twice over. Errors arriving at TracePath over OTLP are symbolicated at ingest. And the engine ships as a standalone OpenTelemetry Collector processor that is drop-in compatible with Honeycomb's source_map_symbolicator, so you can symbolicate inside your own pipeline, with or without TracePath behind it.

Which bundlers and frameworks are supported?

Anything that emits standard source maps: Vite, webpack, esbuild, Rollup, Metro, and the frameworks built on them. Inline sourceMappingURL data URIs are supported, and maps with missing source file names still resolve line, column, and function name.

Does it symbolicate Dart and Flutter?

Yes. The same engine reads Dart obfuscation maps and resolves obfuscated Flutter and Dart stack traces back to your original symbols. It runs through the same compiled-cache pipeline as JavaScript, and the benchmark above shows both cache modes surviving every load scenario, including the memory-starved OOM box.

Does it symbolicate iOS and Swift crashes?

Yes. Upload your build's .dSYM and the same engine resolves stripped Swift and Objective-C crash addresses back to file, line, and function, with inline frames expanded. dSYMs upload through the same per-project token and POST endpoint as your source maps, so a single Xcode build phase or a curl in CI keeps every release symbolicated.

Does it symbolicate Android crashes?

Yes. Release builds run R8, which renames classes and rewrites line numbers, so crashes arrive obfuscated. Upload the build's mapping.txt and the same engine retraces every frame back to the original class, method, file, and line, expanding the calls R8 inlined. The Gradle plugin injects a per-build UUID and uploads the mapping for you, through the same per-project token and POST endpoint as your source maps and dSYMs. On the OpenTelemetry path it reads the same app.debug.proguard_uuid attribute as Honeycomb, so a migrating app keeps its instrumentation.

Are my source maps exposed publicly?

No. Maps are uploaded to your TracePath instance's blob storage and used server-side only. They are never served to browsers, so you can keep .map files out of your deployed assets entirely.

What happens to errors from a build without maps?

They stay minified but still group correctly. Column numbers keep frames distinct on line one, and resolved function names are excluded from the grouping hash, so existing groups don't reshuffle when you upload maps later.