Invalid call to FLinkerLoad::Preload while using the EDL when using Data Asset Linker and Get User Data in a Control Rig

We see the following error sometimes when running the game with cooked content.

Assertion failed: !GEventDrivenLoaderEnabled || !bLockoutLegacyOperations || !(1) […\Engine\Source\Runtime\CoreUObject\Private\UObject\LinkerLoad.cpp] [Line: 4530] 
Invalid call to FLinkerLoad::Preload while using the EDL. '1928920464' should have been reported via GetPreloadDependencies instead.

The asset in question is UUserDefinedStruct, which is only referenced in the Control Rig via the namespace in calls to GetUserData in the graph (on the Construction event). In the Reference Viewer, we do see the connection between the Control Rig and the asset for the UUserDefinedStruct. The SkeletalMesh has Data Asset Linker that is pointing to a Primary Data asset.

This Primary Data asset is derived from a base Primary Data Asset blueprint. This base Primary Data Asset contains a variable that is an Array of UUserDefinedStruct mentioned earlier.

Depending on the order the load calls come into FAsyncLoadingThread determines if the error hit or not. Depending on whether the UUserDefinedStruct is completely loaded before the Control Rig determines if we hit the error or not. It seems like even though a hard reference between the Control Rig and the UUserDefinedStruct is being created. However, when loading the content in the game the Control Rig seems to be requesting data similar to how a soft refence would.

Is there something we are missing that would make this error go away? I have not found any documentation on how best to use the Data Asset Linker and what is needed to make things get cooked correctly. The Get User Data function is returning the array of this structure which is why the link is created between the Control Rig and this UUserDefinedStruct.

Thank you.

Hey Brett,

could you give a bit more context on what game configuration you’re using?

Is this happening on a packaged game or are you running the game locally specifically with the cooked loose files on disk?

I’m asking because the EDL loader is our old loading path that’s only used in a few specific cases.

In 5.4, cooked content should be placed in the Zen store and utilize the new Zen loader, which is likely to not exhibit this issue.

There are some edge cases in the EDL that we won’t be fixing and moving to the new loader is the recommended approach in this case.

Could you check if your project has the "Use Zenserver as cooked output store" option in the Packaging settings enabled?

You can also verify by checking that your Saved/Cooked/ directory does not contain any .uasset/.ubulk files.

Thanks,

Sebastian

We see this issue running Development Win64 (I have not tried other platforms yet). I am cooking the game from the editor, then launching Development from visual studio.

Use “Zenserver as cooked output store” is not set for our project.

Thanks for the info!

Is there a specific reason you’re not using Zen as cooked output store currently?

It’s enabled by default for new 5.4 projects, should provide better performance and supports lots of our ongoing cooking and packaging improvements, so it will replace loose files completely at some point.

Could you test if the issues still appear with that option enabled?

That would help us narrow down whether we’re looking at an EDL specific issue or some generic problem.

Best,

Sebastian

Enabling “Use Zenserver as cooked output store” does seem to resolve the original issue.

However, it appears we need to have the editor running to run a cooked build with that setting. Is there a command line option or something else we would need to set to run without the editor also running for a cooked build? It is less than ideal to need to have both the editor and the game running.

Hey Brett,

usually the engine should start Zenserver in the background if it’s needed on-demand, no Editor required. I’m currently checking with the team if this is a known issue in 5.4, we’ve changed the logic behind this a few times in recent releases.

In the meantime, you can also easily start Zenserver manually, e.g. by running ZenDashboard.exe from Engine/Binaries/Win64/ and then choosing Tools -> Start Zen Server. It should keep running this way, so this only needs to happen once until the machine is rebooted.

Best,

Sebastian

Just a follow up on this:

Regarding Zen server startup, there’s also an option of changing the configuration in your DefaultEngine.ini to make sure that Zenserver does not shutdown if you Editor or sponsor process closes. This would still require starting the Editor or Zen at least once after each reboot though. In the future we aim to install Zenserver as a service so this is no longer necessary.

Here is the required config setting to keep Zen running when the Editor closes:

[Zen.AutoLaunch]
LimitProcessLifetime=false

As for the actual error, if you want us to further investigate we would ideally need a minimal project that reproduces the error, a log from your Editor run with -LogCmds=“LogStreaming VeryVerbose” and some more details (e.g. a screenshot of the graph, settings) on the controlrig setup.

Kind Regards,

Sebastian

Hey Brett,

apologies for the delay, I had to clarify some things internally.

Let me prefix this with our intentions for the future:

We’re planning to have Zenserver installed as a service by default, so it will run by default when users start their machine.

This would remove any issues around lifetime management and the question on whether Zenserver is running at any given time. Our Editor tools all do start Zenserver automatically, but the client use cases (what we call “Zen streaming”) where a local build or a build running on a console devkit loads data from Zenserver on demand are not set up to autostart Zen (and in the case of a console devkit it’s not easily possible to have the dev kit start something on the host on demand).

The service install should remove all the extra logic the Editor tools and both clients and tools can assume that the local Zenserver will be running all the time, without user intervention necessary.

This has not been implemented yet, but we’re planning to have this set up around 5.8 (no promises on that specific version, though).

As for starting Zenserver currently:

There are several startup parameters that need to be correctly passed to Zenserver to make sure it’s configured correctly.

There is tooling that helps with starting a Zenserver process with the correct parameters for a project:

In case you are using UShell, there’s a built-in command to start/stop a server, but it’s still requires launching UShell to run the command:

.zen start / .zen stop

Since UShell is not a very commonly used tool by licensees you will likely not use it currently.

There’s also a command-line tool and I’ve got some info on it from a colleague:

The engine provides a program named ZenLaunch that does the work of starting zenserver correctly based on user and project configuration. You can build and run ZenLaunch (specifying your .uproject on the commandline) and it will launch zenserver for you. By design it insists you provide a "sponsor process id" also, because if the configuration indicates that zenserver runs in limited lifetime mode, we must know the process(es) that zenserver must stick around for.They suggested looking at Engine\Source\Programs\AutomationTool\BuildGraph\Tasks\ZenExportSnapshotTask.cs as an example where Zenlaunch is used in the engine.

You will need to build it first, since it might not be compiled by default and then it should be run like this:

D:/Path/to/Engine/Binaries/Win64/ZenLaunch.exe D:/Path/to/Project/ProjectName.uproject -SponsorProcessID=XXXFor the editor tool use case, the SponsorProcessID should be the process that is launching Zenserver and requiring it to stay alive for its work.

However, this doesn’t work in the Zen streaming case, where you haven’t started the game yet and you don’t know a processID beforehand.

If you have set LimitProcessLifetime=false then this can be any valid process id, but it is not used since Zen will not automatically shut-down. If limited lifetime mode is still on, then this should be something that lives for as long as your game process, e.g. the processID of the IDE launching it or the console host hosting your launch command.

Hope this helps.

Kind Regards,

Sebastian

Is there a command line that could be run to start the service if we detect that is not running when the game boots up?

Thank you for the information, this gives me some things to discuss with the team about how to move forward.

Thank you.