
Mobile Ad SDK Crash Debugging: AdMob & Mediation
Ad SDK crashes are one of the most infuriating classes of mobile bug because the stack trace rarely points at your code. An AdMob crash usually surfaces as a wall of GAD prefixed frames, an adapter's native symbols, or a bare EXC_BAD_ACCESS with no obvious trigger — and it only appears after you ship, when a live ad network serves a creative your test environment never saw. This guide walks through the ad SDK crash classes we see most often in production: GADInvalidArgumentException from bad setup, mediation adapter version skew, rewarded ad lifecycle bugs, WebView-rendered ad crashes, and consent SDK failures. We'll show concrete code that reproduces each one and give you a repeatable workflow for attributing and fixing them fast.
Why Ad SDK Crashes Are Different
A crash in your own feature code is usually deterministic: the same input produces the same fault. An ad SDK crash is different because most of the executing code is third-party, and its behavior changes at runtime depending on which network wins an auction and which creative renders. The Google Mobile Ads SDK, Meta Audience Network, and the mediation adapters that stitch them together load their own native binaries and web views, so one app can host several crash-prone runtimes at once.
This is broader than the generic third-party SDK problem we covered in our Third-Party SDK Crashes guide, because ad stacks have a unique failure mode: mediation. When AdMob mediates to AppLovin, ironSource, Unity Ads, or Mintegral, the adapters must match both the Google Mobile Ads SDK version and each network's own SDK version. A skew anywhere in that matrix produces crashes that only appear for the slice of users who hit the mismatched network.
GADInvalidArgumentException: The Setup Crash
The most common AdMob crash happens before any ad is even served. GADInvalidArgumentException is thrown when the SDK is initialized with a bad or missing value, and it traps early in GADMobileAds.sharedInstance().start() or on the first ad request. Per Google's AdMob iOS troubleshooting guide, the three usual culprits are a missing GADApplicationIdentifier in Info.plist, an ad unit ID that does not match the app, and an SDK/adapter version mismatch.
On iOS, the GADApplicationIdentifier key must be present and set to your real app ID before any ad loads. A missing or misspelled key crashes with a clear message, but the value is easy to get wrong when you copy config between build variants.
<key>GADApplicationIdentifier</key>
<string>ca-app-pub-3940256099942544~1458002511</string>The string is the app ID, not an ad unit ID. Passing an ad unit ID (the ca-app-pub-.../... form with a slash) where the app ID belongs, or passing an interstitial unit ID into a banner slot, throws GADInvalidArgumentException at request time. Keep a single source of truth for IDs and validate it per build configuration rather than hardcoding it in each ad call site.
Mediation Adapter Version Skew
Mediation crashes are the hardest to diagnose because they are environmental. Each adapter you add — for AppLovin, ironSource, Unity Ads, Mintegral, or Meta Audience Network — declares a compatibility range against the Google Mobile Ads SDK, and Google publishes the exact pairing in its mediation documentation. When the adapter and the network SDK drift apart, the adapter calls a symbol that no longer exists, and you get a NoSuchMethodError on Android or an unrecognized selector on iOS, often labeled as an adapter crash rather than your own.
The fix is to pin versions explicitly and update them as a unit. Never float the Google Mobile Ads SDK independently of its adapters.
dependencies {
implementation("com.google.android.gms:play-services-ads:23.2.0")
implementation("com.google.ads.mediation:applovin:12.3.0.1")
implementation("com.google.ads.mediation:ironsource:7.5.1.0")
implementation("com.google.ads.mediation:unity:4.11.2.0")
}Each adapter version encodes the network SDK version it wraps. When you bump one, bump the whole set together, then check the adapter's own release notes before shipping. The Google Mobile Ads SDK release notes list the minimum adapter versions for every release — treat that page as a required checkpoint in your upgrade checklist.
Rewarded Ad Lifecycle Crashes
Rewarded ads are the most crash-prone format because they are driven by asynchronous callbacks that outlive the view controller that started them. The classic failure is a reward callback firing after the presenting view controller or its delegate has been deallocated, producing an EXC_BAD_ACCESS with no surviving symbol to point at your code.
class RewardedAdController {
var rewardedAd: GADRewardedAd?
func load() {
let request = GADRequest()
GADRewardedAd.load(withAdUnitID: "ca-app-pub-3940256099942544/1712485313",
request: request) { [weak self] ad, error in
guard let self else { return }
self.rewardedAd = ad
self.rewardedAd?.fullScreenContentDelegate = self
}
}
}The [weak self] capture keeps the handler from touching a deallocated controller; without it, the reward callback can fire into freed memory. Per Google's rewarded ads guide, every delegate callback must be defensively coded against a nil or deallocated presenter.
A second rewarded ad trap is presenting from a background thread. Full-screen ad presentation is main-thread-only, and a present(_:animated:) called from a networking callback queue crashes with a UIKit main-thread checker warning before the ad even shows.
Banner and Native Ad View-Hierarchy Crashes
Banner and native ads crash on layout and containment mistakes. The two we see most are adding the same ad view to the hierarchy twice, and constraint conflicts between the ad's intrinsic size and a fixed frame. Adding a GADBannerView or a native ad view that is already a subview triggers an "view was added as a subview twice" assertion, while pinning both width and height constraints that disagree with the ad's measured size throws an Auto Layout exception at render time.
The safe pattern is to create the ad view once, add it once, and let the ad SDK drive sizing. For a banner, set the ad size explicitly; for native ads, reuse the same GADNativeAdView instance instead of rebuilding it on every reload. As in our Auto Layout crash debugging guide, the constraint rules apply unchanged — ads just add an owner that mutates its size asynchronously.
WebView-Rendered Ad Crashes
A surprising share of AdMob crashes happen inside the web view that renders HTML creatives. Banner and native ads can render through WKWebView on iOS and WebView on Android, so an ad crash can surface as a JavaScript exception, a WebKit process termination, or a WebView thread violation that looks nothing like an ad problem. When the content process dies mid-render, the crash lands in WebKit frames with no GAD symbol at all.
If you have already read our WebView crash debugging guide, most of the tooling carries over: capture the WebView's console output, isolate ad loads into their own process where the platform supports it, and correlate WebKit terminations with ad-request timing in your crash reporter. The telltale sign that an ad is responsible is a spike in WebView crashes that coincides with a specific network's fill.
Consent SDK (Google UMP) and ATT Interaction
The Google User Messaging Platform (UMP) SDK, which handles GDPR and ATT consent, crashes in its own specific ways. A common one is calling UMPConsentInformation.sharedInstance.requestConsentInfoUpdate before the SDK has been told which ad technology providers to check, or racing the consent flow against the first ad request. Per Google's UMP quick start, the request must complete before any ad load, and the SDK must be initialized with a valid provider list.
ATT adds a second layer. When the app requests tracking authorization via App Tracking Transparency at the same time the ad SDK is initializing, the consent state can change under the SDK's feet, and a network adapter that assumed a fixed state crashes. Sequence the flows: consent first, then SDK init, then ad requests — and never fire an ad request before the consent callback returns.
SKAdNetwork and Ad Network Attribution Failures
Ad SDK crashes are not always classic crashes. A missing SKAdNetwork entry produces a silent failure where conversions stop being attributed, but an incomplete SKAdNetwork items array can trigger an exception when the SDK validates its configuration. Every network needs its SKAdNetwork ID in Info.plist, kept in sync with each network's current requirements.
The Meta Audience Network SDK validates SKAdNetworkItems and ATT status at init; a mismatch between what Meta expects and what the app declares produces an init-time exception that looks like a Meta bug but is configuration drift.
Pinning Versions and the Compatibility Matrix
Because ad crashes are environmental, the highest-leverage fix is a version matrix you control. Record the Google Mobile Ads SDK version, each network SDK and adapter version, and the OS range in one place, and gate releases on it. When a crash clusters on one OS version or network, the matrix tells you whether it is version skew or a genuine SDK bug.
The Google Mobile Ads SDK release notes and each network's changelog are the authoritative source for the pairing. Automate a check in CI that fails the build when the declared adapter versions fall outside the ranges the current SDK supports, and you will eliminate the entire class of "it worked until we upgraded one thing" crashes.
Attributing the Crash to the Ad SDK
Before you blame the ad SDK, prove it. Symbolicate the crash and look for the fingerprint frames: GAD prefixed symbols on either platform, adapter class names like APL for AppLovin or IS for ironSource, and WebKit frames for HTML creatives. If the crash report shows a clean GAD frame at the top with your code nowhere in the stack, it is an SDK-originated crash — file it with the network and pin or downgrade the version while you wait.
A practical triage workflow looks like this:
- Reproduce with a test ad unit. Switch to Google's sample unit IDs to confirm the crash is not your configuration.
- Check the matrix first. Version skew between SDK and adapters is the single most common cause, so audit that before touching code.
- Isolate the format. Narrow the crash to rewarded, banner, native, or interstitial — the fixes are format-specific.
- Audit delegate and closure lifetimes. Confirm every ad callback uses a weak capture and every presenter is still alive.
- Correlate WebKit and consent timing. HTML creative and consent races produce crashes that hide outside
GADframes. - Symbolicate and group. Deduplicate the crashes by network and adapter so you can see frequency, not just one instance.
Most ad SDK crashes are fixable without a single line of ad code, because they come from configuration, version skew, or lifecycle mistakes in the surrounding app. Instrumenting them properly is the difference between guessing and knowing.
That is exactly what Bugspulse is built for. Instead of losing an ad crash to a wall of third-party symbols, you get symbolicated traces, session context, and crash groups that tell you which network and adapter is responsible — and whether it affects ten users or ten thousand. With privacy-first error data that keeps ad context without leaking user identifiers, you can ship ad updates with confidence.
Ad monetization only pays off when the app stays alive to show the ad. Pin your versions, guard your delegate lifetimes, sequence your consent flows, and attribute every crash to its real owner. Ready to stop chasing invisible ad crashes? Create a free Bugspulse account and start triaging your AdMob and mediation crashes today.