Quick answer: Remote catalog updates fail when InitializeAsync has not completed before CheckForCatalogUpdates runs, the CDN caches the .hash file, or the Addressable profile’s RemoteLoadPath does not match the actual CDN URL. Fix the call order, set proper cache headers, and verify your profiles.
Here is how to fix Unity Addressables remote catalog updates that silently fail. You push a new content build to your CDN, but players keep loading stale assets. CheckForCatalogUpdates returns an empty list, UpdateCatalogs reports nothing to update, and your hot-fix content never reaches the client. Addressables catalog updates involve multiple moving parts — the hash file, the JSON catalog, CDN caching, and local caching — and a failure at any point causes the entire update pipeline to silently return “nothing to do.”
The Symptom
You build content with “Build Remote Catalog” enabled. You upload the catalog_YYYY.MM.DD.HH.MM.SS.hash and catalog_YYYY.MM.DD.HH.MM.SS.json files (along with updated asset bundles) to your CDN. In the client, you call CheckForCatalogUpdates and the result list is empty. Alternatively, the result contains a catalog locator, but UpdateCatalogs completes without actually downloading new bundles. Assets loaded after the update are still the old versions.
The problem may only appear in builds, not in the Editor. Editor play mode often uses “Use Asset Database” which skips remote loading entirely. Or it may only appear on certain platforms — iOS caches more aggressively than Android, for instance.
In rare cases, the update appears to work but throws cryptic errors later: RemoteProviderException, InvalidKeyException, or hash mismatch warnings buried in the Addressables event viewer.
What Causes This
1. InitializeAsync not awaited before CheckForCatalogUpdates. This is the single most common cause. Addressables.InitializeAsync() loads the local catalog and sets up the resource locator system. If you call CheckForCatalogUpdates before initialization completes, the check has no baseline catalog to compare against and returns an empty list. There is no exception — the API simply reports no updates.
2. CDN caching the hash file. The remote catalog update system works by downloading the .hash file first and comparing it to the locally cached version. If your CDN (CloudFront, Cloudflare, Fastly, or a custom nginx setup) caches the hash file, clients receive the old hash, conclude nothing has changed, and skip the catalog download. The hash file is typically a few bytes — CDNs cache small files aggressively by default.
3. Catalog hash mismatch from partial uploads. If you upload the new catalog JSON but the hash file from the previous build is still in place (or vice versa), the client detects a change, downloads the catalog, but the hash verification fails. Addressables discards the downloaded catalog and falls back to the local version without notifying your code. Always upload hash and JSON atomically.
4. Wrong Addressable profile active during build. The RemoteLoadPath is baked into the catalog at build time. If you build with the “Default” profile pointing to http://localhost/ instead of your production CDN URL, the shipped catalog tries to fetch updates from localhost. This fails silently because the hash file request simply times out or 404s, and CheckForCatalogUpdates returns empty.
5. Build ID mismatch between app and content. When you make a new player build, it embeds a catalog version. If the remote catalog was built with a different Addressables version or a different app build, the version strings may not match. The system considers them incompatible and ignores the remote catalog.
The Fix
Step 1: Ensure correct initialization order.
using UnityEngine;
using UnityEngine.AddressableAssets;
using System.Collections;
using System.Collections.Generic;
public class AddressableUpdater : MonoBehaviour
{
IEnumerator Start()
{
// Step 1: Wait for Addressables to fully initialize
var initHandle = Addressables.InitializeAsync();
yield return initHandle;
Debug.Log("Addressables initialized.");
// Step 2: Check for catalog updates
var checkHandle = Addressables.CheckForCatalogUpdates(autoReleaseHandle: false);
yield return checkHandle;
List<string> catalogsToUpdate = checkHandle.Result;
Debug.Log($"Catalogs needing update: {catalogsToUpdate.Count}");
if (catalogsToUpdate.Count > 0)
{
// Step 3: Download and apply the updated catalogs
var updateHandle = Addressables.UpdateCatalogs(catalogsToUpdate, autoReleaseHandle: false);
yield return updateHandle;
Debug.Log($"Updated {updateHandle.Result.Count} catalog(s).");
Addressables.Release(updateHandle);
}
else
{
Debug.Log("No catalog updates available.");
}
Addressables.Release(checkHandle);
// Step 4: Now safe to load assets
LoadGameAssets();
}
void LoadGameAssets()
{
// Your asset loading logic here
}
}
The critical pattern is the sequential yield return chain: InitializeAsync must complete before CheckForCatalogUpdates, which must complete before UpdateCatalogs. Skipping any step or running them in parallel causes silent failures.
Step 2: Configure CDN cache headers for the hash file.
For CloudFront, create a behavior that matches *.hash files and sets Cache-Control: no-cache, no-store, must-revalidate. For Cloudflare, add a Page Rule for the hash file path with “Cache Level: Bypass.” For nginx:
# nginx configuration for Addressables CDN
location ~* \.hash$ {
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
expires 0;
}
# Allow aggressive caching for bundles (they are content-addressed)
location ~* \.bundle$ {
add_header Cache-Control "public, max-age=31536000, immutable";
}
Bundle files are content-addressed (their filenames include a hash), so they can be cached forever. But the hash and catalog JSON files must never be cached, because they are the mechanism by which clients discover new bundles.
Verifying the Fix
Enable the Addressables Event Viewer (Window > Asset Management > Addressables > Event Viewer) and set the play mode to “Use Existing Build.” This forces the Editor to use the same remote loading path as a real build. Watch the event viewer for catalog download events. You should see a network request for the hash file, then the catalog JSON, then any updated bundles.
If the event viewer shows no network requests at all, the problem is in the initialization order or the RemoteLoadPath. If it shows a request for the hash file that returns a cached response, the CDN headers are wrong. If it shows a catalog download followed by a hash mismatch error, you have a partial upload.
Profile validation checklist. Open Window > Asset Management > Addressables > Profiles. Confirm that the active profile’s RemoteBuildPath and RemoteLoadPath point to your production CDN. For multi-platform builds, use profile variables like [BuildTarget] in the path. A common mistake is building for StandaloneWindows64 with a path that includes /Android/ from a previous build.
“The Addressables catalog update system has exactly zero tolerance for race conditions. InitializeAsync, CheckForCatalogUpdates, UpdateCatalogs — always sequential, always awaited.”
Platform-Specific Gotchas
iOS App Transport Security. If your CDN uses HTTP instead of HTTPS, iOS silently blocks the catalog download. The hash file request fails, and CheckForCatalogUpdates returns empty. Either use HTTPS or add an ATS exception in your Info.plist.
Android split APKs (AAB). When using Android App Bundles, the local catalog is inside the APK. If the Play Store serves a split APK that does not include the local catalog, InitializeAsync fails. Ensure the Addressables settings have “Build Remote Catalog” enabled and that the local catalog is included in the base module.
WebGL. Browser caching adds another layer on top of CDN caching. Even if your CDN serves no-cache headers, the browser may use its own disk cache. Appending a cache-busting query string (?v=timestamp) to the hash file URL can help, but requires custom modifications to the RemoteLoadPath.
Related Issues
If the catalog updates successfully but assets still load old versions, the issue may be bundle caching rather than catalog caching — see Asset Bundle Caching Issues. If Addressables throw InvalidKeyException after an update, the asset keys in your code may reference addresses that were renamed or removed in the new content build — see Addressables InvalidKeyException.