Build1 distinct publisher3 min readUpdated
A DSN check in Application.onCreate looked airtight and passed four builds. The Sentry provider folded into the merged manifest crashed every launch before that code existed.
The Engineer · Build desk
Compiled by The EngineerSomething wrong?How this is made
Two configuration channels were open in this project, and only one of them was ever read. The DSN lived in a gitignored `local.properties` and reached Kotlin through `BuildConfig.SENTRY_DSN` [2]. The self-initialising path reads a DSN from `io.sentry.dsn` manifest meta-data, which this project deliberately never sets [9][10]. The two channels do not meet, so the decision that kept the key out of version control is the same decision that guaranteed the provider would find nothing and throw during process startup [1].
That also means the green build-with-a-DSN was not a second data point. `SentryInitProvider.onCreate` calls `SentryAndroid.init` with no options lambda [9], so it never consults `BuildConfig`, and the variant compiled with a real DSN would have died in the same place [2]. Both variants were checked by compiling them, and compiling is not the phase where this breaks.
The ordering is the whole mechanism. A ContentProvider is installed before `Application.onCreate()` runs [8], which puts every gate an operator normally writes there downstream of every provider a dependency contributed to the merged manifest [3]. A consent check or a branch on a build flag is code that gets its turn after the SDK has already had one. The only condition actually guarding this provider is `ManifestMetadataReader.isAutoInit`, read from manifest meta-data and defaulting to true when the meta-data is absent [9]. The enforceable switch therefore sits in the manifest, alongside the provider declaration, not in application code [4]. A gate in your `Application` class and a gate in the merged manifest are not two ways of expressing one policy; only one of them is in the process early enough to matter.
The verification gap follows from the same ordering. The four checks that passed were a build with the DSN, a build with a blank DSN, `./gradlew test`, and an iOS cross-compile [4]. None of them installs an APK, starts a process, or instantiates a ContentProvider [11], and the fault lives after compilation and before the author's first line [12]. The guard was real, commented, and never once in force [14]. What did find it was reading `app/build/intermediates/merged_manifest/release/AndroidManifest.xml` and seeing a provider nobody wrote [7], plus a phone.
Note who filed the report. Not the crash reporter, which cannot report its own startup failure [6]; logcat did, on a device, at 100 percent of launches [5]. That is consistent with the other finding in the same integration a few hours earlier, when two privacy leaks became visible only by intercepting the actual outbound bytes, one of them carrying a lifter's shoulder injury note in a request payload [13]. Both bugs were invisible to source review and visible to observation of a running process.
For anyone shipping an SDK behind a flag on Android, the useful question is not whether the flag is correct. It is which layer the vendor chose to start itself in, and whether your off switch lives in that layer too.
Follow any of these and your For You feed starts watching them — no settings page required.
Ranked by verification strength, evidence, and original report placement.
ContentProviders are installed before Application.onCreate() runs.
The author states the fix is one line, without specifying its contents in the passage.
The Sentry DSN came from a gitignored local.properties file and was surfaced to Kotlin as BuildConfig.SENTRY_DSN.
Sentry initialization was wrapped in if (BuildConfig.SENTRY_DSN.isNotBlank()) inside the Application class onCreate, with the stated intent that a build with no DSN behaves exactly as if the SDK were absent.
Four checks were green: a build with a DSN, a build with a blank DSN, ./gradlew test, and the iOS cross-compile.
The release APK on a real device crashed on 100 percent of launches, before a line of the author's code ran, with java.lang.RuntimeException: Unable to get provider io.sentry.android.core.SentryInitProvider caused by IllegalArgumentException 'DSN is required', thrown at SentryInitProvider.onCreate line 27 via ActivityThread.installProvider.
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Detailed first-hand artifacts, single uncorroborated source
The account carries unusually specific technical artifacts for a single-source story: a verbatim stack trace with frame and line number, the dependency's provider declaration, the merged release manifest path the author says he inspected, and a disassembly of the shipped 8.50.1 auto-init path. All of it is self-reported by one developer in one post with no independent verification, vendor documentation, or reproduction by another party, which caps evidence well short of high.
One disclosed integration on one device
Adoption evidence is limited to a single solo-developer integration of sentry-android-core into one personal Android app, plus one release-variant install on one physical device. Nothing in the supplied material shows other projects encountering the failure, download or usage figures, or any vendor response, so measured adoption of the described pattern is minimal even though the underlying SDK default is presumably widespread.
Mostly aligned, framing generalizes one SDK default
The headline's '100% of the time' is literally matched by the reported stack trace and the postmortem is scoped and self-critical, so most claims sit close to the evidence. The mild overstatement is generalizing one SDK's documented-style auto-init default, which has a one-line manifest off switch, into a broad statement about Android guarantees, and asserting that the with-DSN variant would fail identically without having installed it.
Contest submission and own-project narrative, no vendor stake
The post opens by declaring itself a submission for DEV's Summer Bug Smash: Smash Stories, which rewards dramatic, well-told failure narratives, and it doubles as promotion of the author's own app and engineering discipline. There is no disclosed commercial relationship with Sentry and the article does not sell a product or service, so incentive pressure is moderate and shapes framing more than facts.
Coherent mechanism, one publisher, one author
Internal coherence is high: manifest merger injection, provider-before-onCreate ordering, auto-init default, and the missing io.sentry.dsn meta-data form a consistent causal chain that matches the reported stack trace. Confidence is nonetheless mid-range because the cluster has one publisher, one uncorroborated author, no vendor or second-practitioner confirmation, and a key derived conclusion left untested on-device.
build
Eleven tables, no indices: 119.1 ms per read, and a tracing pipeline that accepted nothing1 distinct publisher
build
Sentry's defaults shipped a lifter's shoulder injury while the scrubbing policy passed its tests1 distinct publisher
build
One game, two codebases: where parity belongs when you ship native on iOS and Android1 distinct publisher
build
Renovate opens the PR, Gradle's checksum verification fails the build1 distinct publisher
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · August 22, 2026