Skip to content

fix(bundle-jvm): Strip source-set prefix from bundle URLs#3275

Open
romtsn wants to merge 5 commits intomasterfrom
rz/fix/bundle-jvm-symbolicator-url
Open

fix(bundle-jvm): Strip source-set prefix from bundle URLs#3275
romtsn wants to merge 5 commits intomasterfrom
rz/fix/bundle-jvm-symbolicator-url

Conversation

@romtsn
Copy link
Copy Markdown
Member

@romtsn romtsn commented Apr 21, 2026

Strip the [<module>/]src/<sourceset>/<lang>/ prefix from bundle URLs so Symbolicator can resolve source context from JVM stack traces.

JVM stack traces reference classes by fully qualified name (e.g. io.sentry.android.core.ANRWatchDog) with no knowledge of which Gradle module or source-set directory on disk produced them. The previous URL format included the full on-disk prefix (e.g. ~/sentry-android-core/src/main/java/io/sentry/android/core/ANRWatchDog.jvm), so Symbolicator's URL-based lookup against the bundle manifest could never match a stack frame. Stripping the prefix produces URLs that match the package layout Symbolicator expects (~/io/sentry/android/core/ANRWatchDog.jvm).

Because stripping collapses different source sets into the same URL (e.g. src/main/ and src/debug/ both contributing com.example.Foo in an Android build variant), the command now tracks seen URLs and emits a warn! on collision, skipping all but the first-seen file. The warning points users at --exclude so they can scope the bundle to a single variant rather than bundling sources that would otherwise silently overwrite each other in the zip.

Follow-up to #3260, which enabled running bundle-jvm directly on a multi-module project root.

Symbolicator looks up files in the source bundle manifest by URL,
matching the package path from JVM stack traces (e.g. classes report as
io.sentry.android.core.ANRWatchDog with no knowledge of which Gradle
module or source set on disk produced them). The previous URL format
included the full on-disk prefix (e.g.
~/sentry-android-core/src/main/java/io/sentry/android/core/ANRWatchDog.jvm),
so Symbolicator could never resolve source context from a stack trace.

Strip the [<module>/]src/<sourceset>/<lang>/ prefix from the relative
source path when building the URL, so it matches the JVM package layout
Symbolicator expects.

Because stripping collapses files from different source sets into the
same URL (e.g. src/main and src/debug both contributing com.example.Foo
in an Android build variant), track seen URLs and warn-and-skip on
collision. The warning points users at --exclude to scope the bundle
to a single variant.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@romtsn romtsn requested review from a team and szokeasaurusrex as code owners April 21, 2026 16:29
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit fc200c5. Configure here.

Comment thread src/commands/debug_files/bundle_jvm.rs Outdated
Comment thread src/commands/debug_files/bundle_jvm.rs Outdated
romtsn and others added 4 commits April 21, 2026 18:38
Extract the URL dedup + build-output filtering loop out of execute()
into build_source_files, returning a Vec<UrlCollision> alongside the
Vec<SourceFile>. The caller (execute) now logs the warning for each
collision; the function itself is pure and testable without a logger
mock.

Covers: first-seen semantics on variant collision (src/main beats
src/debug by walk order), including the fields the warning prints
(url, skipped_path, kept_path); and distinct URLs passing through
without spurious collision records.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
JVM_EXTENSIONS already included `clj` and `cljc`, so Clojure files under
`src/main/clojure/` were collected — but `clojure` was missing from
SOURCE_SET_LANGS, so the prefix wasn't stripped. URLs came out as
`~/module/src/main/clojure/com/example/foo.jvm`, which Symbolicator
would never match against a Clojure stack frame.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
WalkBuilder from the ignore crate yields entries in filesystem order,
so the first-seen winner of URL collision resolution depended on the
underlying disk layout. Two machines walking the same source tree
could bundle different variants when src/main/ and src/debug/
contributed the same FQCN, breaking build reproducibility.

Add an opt-in sort_entries flag to ReleaseFileSearch that enables
WalkBuilder::sort_by_file_name, and turn it on for bundle-jvm. The
sourcemaps callers aren't exposed to the collision issue so they keep
the current (unsorted, slightly cheaper) behavior.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant