the symptom, in your words

"A custom asset extension can lose a registration race against an engine type"

✓ verified on 26.08.05
lane Tooling & environmentposted

▸ SYMPTOM

  • A custom [AssetType] resource type stops resolving. ResourceLibrary.GetAll<T>() returns an empty sequence.
  • There is no error, no warning, and no console line. The registration just does not take.
  • The same commit on the same engine build behaves differently between launches. One session has the custom type fully live. The next has it completely dark.

▸ CAUSE

The engine registers its own type on some extensions out of the box. One example is [AssetType(Name = "Ammo Type", Extension = "ammo", Category = "Game")], which ships with a stock asset to match. A project-defined resource type that claims the same letters collides with the engine type.

The collision is a race, and which side wins is decided per editor launch, not fixed by the commit. The same commit on the same engine build produced opposite outcomes across two launches ten minutes apart. One launch had the custom type live. The next had it dark.

The losing type is silent. ResourceLibrary.GetAll<T>() for that type returns an empty sequence with no diagnostic. Worse, every file on that extension then deserializes as the engine's type instead. A consumer that treats "empty result" as "nothing of mine exists" can instead receive a foreign asset with every field at its C# default, silently reachable wherever the empty-list case was assumed harmless.

▸ FIX

Audit the extension before you commit to a custom asset type.

  1. Open asset_types in a live editor.
  2. Find every registration that claims your extension. Two registrations can share the same display Name, so check the Category and which one actually claims the Extension. Never match on the name string alone.
  3. If the engine or a base addon already claims those letters, choose a different extension. An extension collision is blocking, not cosmetic.
  4. In code, make any path that calls GetAll<T>() for a type that shares an extension with an engine asset detect the empty or foreign-data case explicitly, then degrade instead of reporting green.

▸ WHY IT WORKS

The registration outcome is session-scoped luck, so a green result on one launch is not evidence the type is safe. Reading asset_types in a live editor shows which type actually holds the extension this session. Ruling out any letters the engine or a base addon already claims removes the race entirely, because there is no second registrant to lose to.

Verified on engine 26.08.05: seen in a real project.
s&box moves fast; an undated fix is a liability. Spot a stale detail?
changelog
  • Published

Want to know when new guides or fixes drop? Join the community to help build this out. Report gotchas, flag outdated fixes, or just lurk.

Join the Discord