There are few logs more disheartening in mobile development than Error Code 1001: No Fill. You have integrated the SDK, followed the documentation, and successfully initialized the library. Yet, when you request an ad, the onError callback fires immediately.
For developers aiming to monetize via the Meta (Facebook) Audience Network, this error is the primary blocker between development and revenue. The good news is that in 90% of cases, your integration code is perfectly fine. The issue lies in the configuration or the inventory supply chain.
This guide provides a rigorous technical breakdown of why 1001 occurs and details the specific, code-level solutions to resolve it for Android and iOS in 2025.
The Root Cause: What is Error 1001?
To fix the error, you must understand the mechanism behind it. Error 1001 does not mean the SDK failed to communicate with Meta's servers. It means the server received your request but chose not to return an ad.
The Ad Selection Logic
When your app calls loadAd(), the following happens "under the hood":
- Request: The SDK sends a payload containing the Placement ID, device ID (IDFA/GAID), app metadata, and context.
- Auction: Meta runs a real-time auction or checks inventory availability for that specific user profile.
- Decision: If no advertiser bids above your floor price, or if the user has no ad profile (common in testing), the server returns a "No Fill" signal.
In a test environment, Meta deliberately blocks "live" ads to prevent invalid impression fraud. If you do not explicitly register your device as a tester, you will receive Error 1001 by default.
Solution 1: The Test Environment Configuration
The most common cause of Error 1001 during development is failing to register the device hash. Meta requires specific whitelisting to serve test ads.
Step 1: Locate the Hash ID
Run your app on a physical device (simulators often fail to retrieve ads regardless of settings). Trigger an ad load. Watch your Logcat (Android) or Xcode Console (iOS).
You will see a log entry resembling this: Test mode device hash: <HASH_ID>
Step 2: Implement Explicit Test Registration
Do not rely on the Meta Monetization Manager UI alone to add test devices. Hardcoding the test flag during debug builds is the most reliable method to force a 100% fill rate for testing.
Android Implementation (Kotlin)
Place this code inside your Application class or main Activity before initializing the SDK.
import com.facebook.ads.AdSettings
import com.facebook.ads.AudienceNetworkAds
import android.util.Log
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
// 1. Enable debug logging to see the Hash ID easily
AdSettings.setIntegrationErrorMode(AdSettings.IntegrationErrorMode.INTEGRATION_ERROR_CRASH_DEBUG_MODE)
// 2. Add your device Hash ID (Found in Logcat)
// multiple devices can be added to the list
AdSettings.addTestDevice("YOUR_DEVICE_HASH_ID_HERE")
// 3. Initialize the SDK
AudienceNetworkAds.initialize(this) { result ->
Log.d("MetaAds", "SDK Initialized: ${result.message}")
}
}
}
iOS Implementation (Swift)
Add this logic to your AppDelegate or the initialization block of your Ad Manager singleton.
import FBAudienceNetwork
func initializeMetaAds() {
// 1. Set the Hash ID for the test device
// This allows the server to bypass the auction and serve a test creative
FBAdSettings.addTestDevice("YOUR_DEVICE_HASH_ID_HERE")
// 2. Clear previous hashed IDs if you are switching test phones often
// FBAdSettings.clearTestDevices()
// 3. Initialize SDK
FBAudienceNetworkAds.initialize(with: nil) { result in
if (result.isSuccess) {
print("Meta Audience Network initialized successfully")
} else {
print("Failed to init: \(result.message ?? "Unknown Error")")
}
}
}
Note: Always wrap
addTestDevicecalls in a check for your debug build configuration (e.g.,#if DEBUG) so you don't accidentally enable test ads in production.
Solution 2: Validation of Placement IDs
If you are using test devices and still receiving 1001, the issue often lies in the Placement ID status.
A valid Placement ID string looks like IMG_16_9_APP_INSTALL#YOUR_PLACEMENT_ID. However, many developers mistakenly use the generic App ID or a deprecated ID.
The Checklist
- Status: Go to Monetization Manager. Ensure the property status is "Ready to Publish" or "Active". If the status is "Idle" or "In Review" for an extended period, fill rates will drop to zero.
- Format Mismatch: You cannot request a Rewarded Video using a Banner Placement ID. The server validates the ad type against the ID. If they mismatch, it returns 1001.
Robust Error Handling Code
You must distinguish between a genuine network error and a No Fill. Here is how to handle the listener properly to debug the specific cause.
// Android: Interstitial Ad Listener Implementation
private val interstitialAdListener = object : InterstitialAdListener {
override fun onInterstitialDisplayed(ad: Ad?) {
Log.d("MetaAds", "Ad Displayed")
}
override fun onInterstitialDismissed(ad: Ad?) {
Log.d("MetaAds", "Ad Dismissed")
}
override fun onError(ad: Ad?, error: AdError?) {
// CRITICAL: Log the sub-code and description
// Error 1001 is No Fill. Error 1000 is Network Error.
Log.e("MetaAds", "Error: ${error?.errorCode} - ${error?.errorMessage}")
if (error?.errorCode == AdError.NO_FILL.errorCode) {
// Fallback logic: Load from a different ad network
loadAdMobFallback()
}
}
override fun onAdLoaded(ad: Ad?) {
Log.d("MetaAds", "Ad Loaded Successfully")
}
override fun onAdClicked(ad: Ad?) {
Log.d("MetaAds", "Ad Clicked")
}
override fun onLoggingImpression(ad: Ad?) {
Log.d("MetaAds", "Impression Logged")
}
}
Solution 3: Mediation and Bidding Configuration
In 2025, most high-yield integrations use App Bidding (via AppLovin MAX, LevelPlay, or Google AdMob Mediation) rather than a pure waterfall.
If you are using Mediation and see Error 1001/No Fill from Meta:
- Bidding Token Issues: Meta Audience Network is a "bidder-only" network for many formats now. The SDK must generate a valid bidding token to pass to the mediator. If the token is null or expired, Meta cannot bid, resulting in No Fill.
- eCPM Floors: If you manually set a high eCPM floor in the Meta console (e.g., $20.00) for testing, Meta will not return an ad unless it can beat that price. Remove floors during initial testing.
Debugging Bidding Tokens (iOS Example)
If you are using a custom mediation adapter, verify the token generation explicitly:
// Check if the bidder token is being generated correctly
let bidderToken = FBAudienceNetworkAds.bidderToken
if let token = bidderToken, !token.isEmpty {
print("Valid Bidder Token: \(String(token.prefix(20)))...")
} else {
print("CRITICAL: Bidder Token is null. Meta cannot participate in auction.")
}
Solution 4: iOS 14+ and ATT Compliance
On iOS, Error 1001 is frequently caused by a lack of tracking permissions. If a user denies tracking via App Tracking Transparency (ATT), Meta cannot personalize ads. While this usually results in generic ads, in low-inventory regions, it results in No Fill.
The Requirement
You must check the tracking status before initializing the SDK.
import AppTrackingTransparency
import AdSupport
func requestTracking() {
if #available(iOS 14, *) {
ATTrackingManager.requestTrackingAuthorization { status in
switch status {
case .authorized:
// High CPM, higher fill rate
print("Authorized: \(ASIdentifierManager.shared().advertisingIdentifier)")
FBAudienceNetworkAds.setAdvertiserTrackingEnabled(true)
case .denied, .restricted, .notDetermined:
// Low CPM, lower fill rate (High chance of 1001)
FBAudienceNetworkAds.setAdvertiserTrackingEnabled(false)
@unknown default:
break
}
// Initialize SDK AFTER this choice
initializeMetaAds()
}
} else {
// Fallback for older iOS versions
FBAudienceNetworkAds.setAdvertiserTrackingEnabled(true)
initializeMetaAds()
}
}
Summary: Troubleshooting Flow
If you are stuck on Error 1001, follow this strict order of operations:
- Is it a Test Build?
- Yes: Add the Device Hash ID in code.
- No: Proceed to step 2.
- Is the Placement Active?
- Check Monetization Manager. Ensure payment details are entered and the property is not flagged for quality violations.
- Are you attempting to run "Live" ads on a Simulator?
- This will never work. Use a physical device.
- Is the User in a supported geography?
- Use a VPN to test US/UK geography if you are developing from a region with low ad inventory.
By isolating the environment (Test vs. Production) and validating the device hash, you can resolve the vast majority of Error 1001 instances. Remember, in production, a 100% fill rate is impossible; robust waterfall/bidding logic is your only safety net against natural inventory shortages.