MonoGame 3.8 Content.Load<T> cache invalidation across processor version changes
0 reputation · 17 Feb 2021, 12:31 UTC
0 reputation · 17 Feb 2021, 12:31 UTC
MonoGame's Content.Load caches compiled assembly references to reduce startup overhead. In version 3.8, the cache key omits processor version metadata, so a content pipeline rebuild that revises type definitions without an explicit CacheVersion attribute results in runtime assets retaining stale type descriptors. This behavior affects any project that rebuilds content modules across iterative development cycles.
Cache invalidation depends on the content root path interpretation; relative paths can produce matching cache entries across separate projects, obscuring version differences. The exact trigger that prompts the engine to purge cached type metadata when a content processor's API surface changes is not documented in the 3.8 release notes, leaving developers to infer purge conditions from project structure.
Which content root path changes invalidate the Content.Load cache in MonoGame 3.8? Does the CacheVersion attribute in the .mgcb project file serve as the sole invalidation mechanism, or are there implicit version comparisons? When migrating compiled content between Windows and Android projects, does the default compression divergence cause silent asset type mismatches despite matching processor versions?
34775 reputation · 17 Feb 2021, 19:04 UTC
The premise needs correcting before the questions can be answered: in MonoGame 3.8, Content.Load<T> does not cache compiled assembly references keyed by processor version, and there is no CacheVersion attribute in the .mgcb format or in ContentManager. What actually exists is much simpler: each ContentManager instance keeps an in-memory dictionary keyed by the asset name string you pass to Load<T>, so repeated loads of the same asset return the same instance. That dictionary lives only for the lifetime of the process (or until Unload()). This reflects the long-standing ContentManager design; if exact internals matter, confirm against the 3.8 source (Content/ContentManager.cs).
RootDirectory only affects how asset names are resolved to file paths; it is not part of a version-aware cache key. Each ContentManager has its own private cache, so two managers with different root directories never share entries, and there is no cross-project cache collision of the kind described. Because the cache is per-process, restarting the game always re-reads whatever .xnb files are on disk.
No — it does not exist. There are also no implicit version comparisons at runtime: Content.Load<T> has no knowledge of processor versions, pipeline metadata, or type descriptors. Versioning happens entirely at build time, when MGCB recompiles your content into .xnb files. You can verify this by searching the MonoGame repository and the .mgcb schema for "CacheVersion" — nothing will turn up.
No silent mismatches, but for a different reason: .xnb files are platform-specific binaries and are generally not portable. Texture compression formats, graphics profile (Reach vs HiDef), and platform targets (DesktopGL vs Android) all change the output, so content must be rebuilt per platform. Loading a mismatched or corrupt .xnb typically throws ContentLoadException rather than silently deserializing wrong types.
If you rebuild the .mgcb with changed processor settings and the game still shows old assets, the cause is almost always build/deploy, not a runtime cache:
A quick diagnostic: delete the game's output directory (bin/), rebuild everything, and rerun. If the asset updates, the runtime cache was never the problem. If it still doesn't, the .xnb itself wasn't regenerated — inspect the MGCB build log.
If you are genuinely seeing stale type descriptors survive a full clean rebuild and redeploy, that would contradict the design above — in that case, the one detail worth sharing is the exact MonoGame version and a minimal repro, because it would point to something outside stock ContentManager behavior (for example, a custom content manager or serializer).
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.