I need to explain a bit on how the reference and loading system in Unreal works first to explain how to figure this out to fix it.
Dependencies in Unreal
Save Time
When an asset is saved Unreal goes through all of the asset’s dependencies and saves them in a list in the uasset itself, called the Imports List. Gathering all the referenced assets takes a little while so it only happens on save time. This is the list that the Asset Registry loads to know what references what, and uses it to populate the information in Reference Viewer and Map View. Since it’s all pre-saved it’s very fast to query.
But since the dependencies get saved into the asset it’s also possible for you to then later on delete one of those dependency assets without the parent asset “knowing” of it. This can happen if you delete the asset directly from the hard drive through Windows Explorer, or through a bad version control file merge. If the deletion of an asset doesn’t happen in Unreal, then Unreal can’t warn you about the asset still being referenced somewhere else and shouldn’t be deleted.
If the asset is suddenly missing without Unreal knowing of it, then when loading the parent asset you’ll see that error as it tries to load a depending asset that doesn’t exist.
Load Time
This dependencies list is also the list that Unreal uses to know what it needs to load with the asset itself. At load time, the linker (you can think of it as the “loader” in this example to be a bit more clear on what it does) reads this list of referenced assets (it’s “dependencies”, or it’s “imports”) and loads them with the asset itself. It does this recursively.
This error that you’re seeing is being emitted at load time, from LogGetPackageLinkerError
in Linker.cpp. If you put a breakpoint in there to see why it’s happening it will not tell you much since assets only know what they reference at load time, not why.
Finding Why an Asset Is Depending on Another Asset
Since assets gather their dependencies at save time, that’s when you should be debugging why it’s trying to add some assets as a dependency.
You’ll need to do some C++ debugging to figure out what is introducing the dependency. You can do it with a launcher build of UE with some breakpoint debugging, or in case you have a source compiled version of UE, you can do it quite quickly with one line code line.
UE5
In UE5, all dependencies are added in FPackageHarvester::TryHarvestImport
→ FPackageHarvester::HarvestImport
.
It’s easiest to use a Conditional String Breakpoint in the debugger to have the breakpoint hit when your desired asset name is encountered.
If those aren’t working for you for some reason and you have the possibility to change the source code, you can also add a conditional break at the top of either of the harvesting functions mentioned above. This is especially easy if you use Live Coding:
if (InObject->GetFName().ToString().Contains(TEXT("BP_YourAsset")))
UE_DEBUG_BREAK();
When you hit that function as it references your unwanted asset dependency, check the stack when that breakpoint is hit for the name of the property or other reason that references your asset. SerializeTaggedProperty
will have the property name for example.
UE4
In UE4 the dependency gathering is a bit different.
You can put a breakpoint in UPackage::Save
, just before Pkg->Mark(OBJECTMARK_TagImp);
.
Or in FArchive& FArchiveSaveTagImports::operator<<( UObject*& Obj )
(or any of its other <<
operators).
Again, you can then see the reason why it’s being referenced from the callstack.
Possible Causes
The most likely reason this is happening is because you are simply referencing the now-missing asset. Maybe there’s a Cast
node in the Blueprint casting to that asset type, a variable of that asset’s type, or a variable referencing that asset. Maybe an array. You’ll find out during the breakpoint debugging.
Best of luck with your hunt!