Stack Traces
Automatic stack trace capture for uncaught exceptions, manual captures, async errors, and native crashes — with source map support for web platforms.
Stack traces show the exact sequence of function calls leading to an error — revealing WHERE it happened, HOW the code got there, and WHAT functions were called.
Automatic Stack Trace Capture#
No additional configuration needed. AbrovaTrace automatically captures stack traces from:
- Uncaught exceptions (with
captureUncaughtErrors: true) - Manual exception captures (with
captureException()) - Async errors (with
initWithZone()) - Platform exceptions from native code
try {
await riskyOperation();
} catch (e, stackTrace) {
await AbrovaTrace.captureException(
e,
stackTrace: stackTrace, // Always include this!
message: 'Operation failed',
extra: {'user_id': 'user_123'},
);
}Reading Stack Traces#
Exception: FormatException: Invalid input
at Parser.parse (lib/parser.dart:42:15) ← where error occurred
at DataService.process (lib/data_service.dart:108:8)
at HomeScreen.loadData (lib/screens/home.dart:55:12)
at _HomeScreenState.initState (lib/screens/home.dart:23:5)
- Top line: Where the error occurred
- Following lines: The call stack (how the code got there)
- File paths & line numbers: Help locate the exact issue
Platform-Specific Stack Traces#
Full Dart stacks with line numbers and method names preserved
JavaScript error stacks with browser info — may need source maps for readability
Full debug info with complete stacks and platform details
Extension context info with Chrome version, background/popup context
Adding Context to Stack Traces#
try {
await processPayment(orderId, amount);
} catch (e, stackTrace) {
await AbrovaTrace.captureException(
e,
stackTrace: stackTrace,
message: 'Payment processing failed',
extra: {
'order_id': orderId,
'amount': amount,
'payment_method': paymentMethod,
},
);
}Native Crash Stack Traces#
Native crashes are detected on the next app launch. When a crash kills the app, it can't report in real-time — so AbrovaTrace detects it on restart.
AbrovaTrace.initWithZone() or AbrovaTrace.init()) — no extra call is needed. AbrovaTrace.close() only flushes pending data and shuts the SDK down.Uploading Source Maps#
For web platforms (Next.js, Flutter Web), upload .map files so production stack traces resolve to your original source files and line numbers.
Where to upload
- Abrova Console — at
console.abrova.ir→ your project → Trace → Source maps & symbols. Set the release version and upload your.mapfiles (several in one go). - Abrova CLI — upload from your build or CI with
abrova-trace sourcemaps upload. See Upload Source Maps. - The Abrova desktop app will offer the same upload when it launches (coming soon).
The release version must match the release field you pass to the SDK at init — that's how the backend pairs the right map with each error.
Uploading needs the member role or higher; deleting uploaded files needs admin or owner. See Roles & Permissions.
Next.js
// next.config.js
module.exports = {
productionBrowserSourceMaps: true,
};After next build, you'll find the .map files next to the chunks under .next/static/chunks/. Up to 500 .map files are accepted per upload, so you can drop them all at once (non-.map files are skipped).
Flutter Web
Build with source maps enabled, then upload the single main.dart.js.map:
flutter build web --source-maps
The map will be at build/web/main.dart.js.map.
dart2js (the compiler that turns Dart into JavaScript) inlines aggressively in --release builds. Some frames will resolve cleanly to your .dart files. Others will resolve to framework internals (js_helper.dart, dart:async) or stay minified (a3v.$0) because the .map simply contains no mapping for those JS bytes.
This is a property of dart2js output — not the resolver. We tell you up front because most teams hit it in production and assume their setup is broken. It isn't.
Where Abrova pulls ahead is context. Enable gesture breadcrumbs (AbrovaTrace.enableGestureBreadcrumbs()) so every issue shows the widget the user tapped right before the error, plus the route, last HTTP call, and any custom breadcrumbs. Combined with the partially-resolved trace, you get a reproducible bug report.
For QA / staging only, you can force less aggressive optimization to get fully resolved traces:
flutter build web --source-maps --dart2js-optimization=O1
Bundle size grows ~30% — fine for staging, not recommended for production.
Best Practices#
Pass the stackTrace parameter when manually capturing exceptions
Include user IDs, screen names, and relevant data in the extra field
Set the release version to correlate errors with deployments
Breadcrumbs show what user did, stack traces show where code failed
Enable debug: true to see stack traces in console during development