Quick answer: Players keep loading old Addressables content because either the catalog hash on the server did not change, the CDN cached the old catalog, or the client never asked for a catalog update. Run Update a Previous Build (not New Build) to bump the hash, invalidate the CDN entries for catalog.json and catalog.hash, and call Addressables.CheckForCatalogUpdates followed by UpdateCatalogs at launch.
Here is how to fix Unity Addressables when remote assets are stuck on a cached version. You upload new bundles to your remote bucket, you confirm the files are there, you launch your game, and you see exactly the same content you saw last week. Maybe one tester reports new content while three report old. Maybe everyone reports old until they uninstall and reinstall. The Addressables system is doing exactly what it was designed to do — cache aggressively for fast loads — but the invalidation signal never reached the client.
The Symptom
You uploaded new content to your CDN. The bundles are visible in the bucket. Maybe you even hit the URL in a browser and downloaded the new file directly. But in-game, players still see the old assets:
Old textures and meshes load. A character you updated still appears with last week’s skin. A level you re-baked still has the old lighting. The asset reference in your code is unchanged — you are loading the same Addressable key — but the bytes returning from the loader are stale.
Inconsistent rollout. Some players get new content immediately, others get nothing. This is the CDN smoking gun — different edge nodes have different cached versions, so the response depends on which edge a given player happens to hit.
Reinstall fixes it. Uninstalling and reinstalling the game makes the new content appear. This proves the bundles are correctly uploaded; the problem is purely on the client invalidation side.
What Causes This
You ran New Build instead of Update a Previous Build. A fresh build generates a new catalog with new hashes for every bundle. Players who already installed against the previous catalog have no idea those new bundles exist — their local catalog still points at the old paths. The new bundles sit on the CDN, completely unreferenced by any client.
Catalog hash file did not get re-uploaded. Addressables uses catalog.hash as a small, cheap probe. If the hash file is unchanged, the client assumes nothing else changed and skips downloading the larger catalog.json. A common deploy mistake is uploading bundles without re-uploading the hash, which freezes the client view of the world.
CDN cached the catalog. Most CDNs default to caching files for hours or days. Even if you uploaded a new catalog.hash, the edge serving your players might still hand out the old one. Until the cache TTL expires or you explicitly purge, no client will see the change.
Client never calls UpdateCatalogs. Addressables does not check for catalog updates automatically on every load. You have to opt in by calling CheckForCatalogUpdates and then UpdateCatalogs. Without this, the runtime keeps using whatever catalog it loaded at InitializeAsync time.
The Fix
Step 1: Use the content update workflow. Find your addressables_content_state.bin from the build that shipped to players (it gets generated next to your build output). In Unity, open Window > Asset Management > Addressables > Groups, click Build > Update a Previous Build, and point it at that bin file. Unity produces a content update package that contains only the bundles whose contents changed, plus an updated catalog that still uses the original hash filename so existing installs can find it.
Step 2: Upload everything and purge CDN edges. Upload the produced bundles, catalog.json, and catalog.hash to the same remote location your shipped build points at. Then issue a cache invalidation against the CDN for those catalog files specifically. You usually do not need to invalidate the bundles themselves — their filenames contain hashes so they are content-addressed.
Step 3: Trigger UpdateCatalogs at launch. Wire the catalog update check into your boot sequence:
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
public class AddressablesBoot : MonoBehaviour
{
private async Start()
{
// Always initialize first so the runtime is ready.
await Addressables.InitializeAsync().Task;
// Ask the catalog if there is anything new.
var checkHandle =
Addressables.CheckForCatalogUpdates(autoReleaseHandle: false);
List<string> catalogsToUpdate = await checkHandle.Task;
if (catalogsToUpdate != null && catalogsToUpdate.Count > 0)
{
Debug.Log($"Updating {catalogsToUpdate.Count} catalogs");
// Re-download the catalog and rebuild the lookup tables.
var updateHandle =
Addressables.UpdateCatalogs(catalogsToUpdate, autoReleaseHandle: true);
await updateHandle.Task;
Debug.Log("Catalog update complete");
}
Addressables.Release(checkHandle);
}
}
Run this once on every boot. The check is cheap (a single small HTTP request for catalog.hash) and an early call here means the rest of your game starts loading already-current content.
Versioning the Remote URL
If you cannot get reliable CDN invalidation, use a versioned URL. Set your RemoteLoadPath profile variable to include a version segment like https://cdn.example.com/{Version}/[BuildTarget]/. Increment the version on every content push. The old URL keeps serving old players, the new URL serves anyone who launches after the catalog update lands. There is no cache to invalidate because every release lives at a unique path.
The trade-off is storage cost — you keep a copy of every historical content version — but for most games the bundles are small relative to the operational simplicity. Combine this with UpdateCatalogs and the only failure mode is a player who refuses to launch your game for several months at a time.
Forcing a Local Cache Clear
For stubborn cases — a tester whose device is wedged, or a development build that needs to fully refresh — you can clear the local AssetBundle cache directly:
using UnityEngine;
using UnityEngine.AddressableAssets;
public class CacheCleaner : MonoBehaviour
{
public void ClearAllCachedBundles()
{
// Drop every cached AssetBundle on this device.
// Next session will redownload everything from remote.
bool success = Caching.ClearCache();
Debug.Log($"ClearCache returned {success}");
}
public async void ClearForLabel(string label)
{
// Targeted clear for a specific Addressables label.
// Useful when a single content pack went bad.
var handle = Addressables.ClearDependencyCacheAsync(label, true);
await handle.Task;
}
}
Use this sparingly. ClearCache can trigger a multi-gigabyte re-download on next launch, and players on metered connections will be unhappy. The targeted ClearDependencyCacheAsync is safer because it only invalidates bundles tied to one label.
“Three caches, three invalidations. Catalog hash, CDN edge, runtime catalog. Miss any one and your players see the past.”
Related Issues
If your catalog update fails outright with a parse or hash mismatch error, see Addressables Remote Catalog Update Failing. For first-load bundle download stalls and timeout tuning, check the catalog endpoint headers and your CDN’s default TTL.
Always Update a Previous Build for shipped games — New Build is for the next major version, not the next patch.