Environment
CLI Version
3.5.0og
Operating System and Architecture
Operating System Version
macOS 15.7.7
Reproduction Steps
main.dart.js
The file extension here is a json but it's actually .map - GitHub rejects .map uploads ... you can change it after downloading
main.dart.js.json
CLI Command
sentry-cli sourcemaps inject main.dart.js main.dart.js.map
Exact Reproduction Steps
- Build any Flutter Web app with sourcemaps:
flutter build web --source-maps. The attached main.dart.js / main.dart.js.map are a minimal stand-in for build/web/main.dart.js(.map) — the map contains the dart2js-specific top-level fields engine and x_org_dartlang_dart2js (values excerpted from a real build, truncated for size; in a real app x_org_dartlang_dart2js is several hundred KB).
- Run
sentry-cli sourcemaps inject main.dart.js main.dart.js.map (or sentry-cli sourcemaps inject build/web, which is what sentry_dart_plugin effectively does).
- Inspect the sourcemap:
jq 'keys' main.dart.js.map.
Map before inject:
{
"version": 3,
"engine": "v2",
"file": "main.dart.js",
"sourceRoot": "",
"sources": ["org-dartlang-sdk:///lib/main.dart"],
"names": ["main"],
"mappings": "AAAAA;AACA",
"x_org_dartlang_dart2js": {
"minified_names": { "global": "A,20845,A0,1916,…", "instance": "A,20845,A0,1916,…" },
"frames": "uzHA+Jeg29ByB;sCAKAAyB;…"
}
}
Map after inject:
{"version":3,"file":"main.dart.js","sources":["org-dartlang-sdk:///lib/main.dart"],"sourceRoot":"","names":["main"],"mappings":";;AAAAA;AACA","debugId":"7d30e0ab-d257-5872-8a48-006edfd6b3e5"}
Results
Expected Results
inject adds the debugId field (and shifts mappings to account for the snippet prepended to the JS) while leaving all other sourcemap content intact — in particular generator-specific extension fields.
Actual Results
The sourcemap is fully decoded and re-encoded, which silently drops every non-standard top-level field:
x_org_dartlang_dart2js — dart2js's extension containing minified_names (global/instance minified-name tables) and frames (inlining records). In the future this is required to deobfuscate minified Dart names and expand inlined frames; on a real Flutter Web build this is ~620 KB of data (e.g. 3,298,985 → 2,680,105 bytes for the example app's main.dart.js.map).
engine — Flutter's engine sourcemap marker.
Root cause (sentry-cli master): in src/utils/sourcemaps.rs, inject_debug_ids → Case 3 (external sourcemap) does
let sm = sourcemap::decode_slice(&sourcemap_file.contents)?; // parse with rust-sourcemap
// ... adjust_regular_sourcemap(): adjust_mappings(&adjustment_map)
sourcemap.set_debug_id(Some(debug_id));
sourcemap.to_writer(sourcemap_file_contents)?; // re-serialize
rust-sourcemap's SourceMap struct only models the standard spec fields (file, tokens, names, source_root, sources, sources_content, ignore_list, debug_id), so everything else is discarded on to_writer.
Logs
> Searching main.dart.js
> Found 1 file
> Searching main.dart.js.map
> Found 1 file
> Analyzing 2 sources
> Injecting debug ids
Source Map Debug ID Injection Report
Modified: The following source files have been modified to have debug ids
7d30e0ab-d257-5872-8a48-006edfd6b3e5 - main.dart.js
Modified: The following sourcemap files have been modified to have debug ids
7d30e0ab-d257-5872-8a48-006edfd6b3e5 - main.dart.js.map
Environment
CLI Version
3.5.0og
Operating System and Architecture
Operating System Version
macOS 15.7.7
Reproduction Steps
main.dart.js
The file extension here is a json but it's actually
.map- GitHub rejects .map uploads ... you can change it after downloadingmain.dart.js.json
CLI Command
Exact Reproduction Steps
flutter build web --source-maps. The attachedmain.dart.js/main.dart.js.mapare a minimal stand-in forbuild/web/main.dart.js(.map)— the map contains the dart2js-specific top-level fieldsengineandx_org_dartlang_dart2js(values excerpted from a real build, truncated for size; in a real appx_org_dartlang_dart2jsis several hundred KB).sentry-cli sourcemaps inject main.dart.js main.dart.js.map(orsentry-cli sourcemaps inject build/web, which is whatsentry_dart_plugineffectively does).jq 'keys' main.dart.js.map.Map before inject:
{ "version": 3, "engine": "v2", "file": "main.dart.js", "sourceRoot": "", "sources": ["org-dartlang-sdk:///lib/main.dart"], "names": ["main"], "mappings": "AAAAA;AACA", "x_org_dartlang_dart2js": { "minified_names": { "global": "A,20845,A0,1916,…", "instance": "A,20845,A0,1916,…" }, "frames": "uzHA+Jeg29ByB;sCAKAAyB;…" } }Map after inject:
{"version":3,"file":"main.dart.js","sources":["org-dartlang-sdk:///lib/main.dart"],"sourceRoot":"","names":["main"],"mappings":";;AAAAA;AACA","debugId":"7d30e0ab-d257-5872-8a48-006edfd6b3e5"}Results
Expected Results
injectadds thedebugIdfield (and shiftsmappingsto account for the snippet prepended to the JS) while leaving all other sourcemap content intact — in particular generator-specific extension fields.Actual Results
The sourcemap is fully decoded and re-encoded, which silently drops every non-standard top-level field:
x_org_dartlang_dart2js— dart2js's extension containingminified_names(global/instance minified-name tables) andframes(inlining records). In the future this is required to deobfuscate minified Dart names and expand inlined frames; on a real Flutter Web build this is ~620 KB of data (e.g. 3,298,985 → 2,680,105 bytes for the example app'smain.dart.js.map).engine— Flutter's engine sourcemap marker.Root cause (sentry-cli
master): insrc/utils/sourcemaps.rs,inject_debug_ids→ Case 3 (external sourcemap) doesrust-sourcemap'sSourceMapstruct only models the standard spec fields (file,tokens,names,source_root,sources,sources_content,ignore_list,debug_id), so everything else is discarded onto_writer.Logs