Engine fails to load or cook map named "Cave" due to conflict with engine asset file

For some reason, the engine has been confusing a level in my game with an unrelated but similarly named engine asset. When I try to load a level called “Cave”, it tries to load /Engine/Content/EngineSounds/ReverbSettings/Cave.uasset as a level, then fails and crashes.

void AGeoGameState::EnterPortal(const FString& DestinationLevelName /*, -- snip -- (other arguments) */)
{
	// build the servertravel map url
	FURL destUrl(*DestinationLevelName);
	if (destUrl.IsLocalInternal())
	{
		// make sure the file exists if we are opening a local file
		if (!GEngine->MakeSureMapNameIsValid(destUrl.Map))
		{
			UE_LOG(Geo, Error, TEXT("AGeoGameState::EnterPortal: The map '%s' does not exist."), *destUrl.Map);
			return;
		}
	}

	/* -- snip -- (add game mode url param with destUrl.AddOption()) */

	// do the level load
	UE_LOG(Geo, Log, TEXT("AGeoGameState::EnterPortal: url = %s"), *destUrl.ToString());
	GEngine->SetClientTravel(GetWorld(), *destUrl.ToString(), ETravelType::TRAVEL_Absolute);
}

When calling this function with the argument “Cave”, that UE_LOG call at the end logs the following:

[2017.05.14-20.10.26:038][367]Geo: AGeoGameState::EnterPortal: url = /Engine/EngineSounds/ReverbSettings/Cave?Game=/Game/Blueprints/GameModes/SingleplayerGameMode.SingleplayerGameMode_C

(I would expect that to look like “/Game/Maps/Singleplayer/Cave”, and every other level in my game works as expected)

This issue was easy enough to hack around - I tried adding a check in EnterPortal() for when DestinationLevelName == “Cave” and load “/Game/Maps/Singleplayer/Cave” instead, but that only fixed the problem in the editor. Turns out that the cooker has the same bug.

CommandUtils.Run: Run: C:\Program Files\Epic Games\UE_4.15\Engine\Binaries\Win64\UE4Editor-Cmd.exe C:\Users\Judd\Documents\Maki\ColorBox\Geoid.uproject -run=Cook -Map=Canyon+Cave+Cavern -TargetPlatform=WindowsNoEditor -fileopenlog -unversioned -iterate -createreleaseversion=Geoid-RC1-Win64 -abslog="C:\Program Files\Epic Games\UE_4.15\Engine\Programs\AutomationTool\Saved\Cook-2017.05.14-14.36.06.txt" -stdout -CrashForUAT -unattended  -UTF8Output
-- snip --
UE4Editor-Cmd: [2017.05.14-21.37.08:717][  0]LogCook:Display: Cooking /Game/Maps/Singleplayer/Cavern -> C:/Users/Judd/Documents/Maki/ColorBox/Saved/Cooked/WindowsNoEditor/Geoid/Content/Maps/Singleplayer/Cavern.umap
UE4Editor-Cmd: [2017.05.14-21.37.09:061][  0]LogSavePackage:Display: Finished SavePackage C:/Users/Judd/Documents/Maki/ColorBox/Saved/Cooked/WindowsNoEditor/Geoid/Content/Maps/Singleplayer/Cavern.umap
-- snip --
UE4Editor-Cmd: [2017.05.14-21.37.09:612][  0]LogCook:Display: Cooking /Engine/EngineSounds/ReverbSettings/Cave -> C:/Users/Judd/Documents/Maki/ColorBox/Saved/Cooked/WindowsNoEditor/Engine/Content/EngineSounds/ReverbSettings/Cave.uasset
UE4Editor-Cmd: [2017.05.14-21.37.09:613][  0]LogSavePackage:Display: Finished SavePackage C:/Users/Judd/Documents/Maki/ColorBox/Saved/Cooked/WindowsNoEditor/Engine/Content/EngineSounds/ReverbSettings/Cave.uasset
-- snip --
UE4Editor-Cmd: [2017.05.14-21.37.11:186][  0]LogCook:Display: Cooking /Game/Maps/Singleplayer/Canyon -> C:/Users/Judd/Documents/Maki/ColorBox/Saved/Cooked/WindowsNoEditor/Geoid/Content/Maps/Singleplayer/Canyon.umap
UE4Editor-Cmd: [2017.05.14-21.37.11:603][  0]LogSavePackage:Display: Finished SavePackage C:/Users/Judd/Documents/Maki/ColorBox/Saved/Cooked/WindowsNoEditor/Geoid/Content/Maps/Singleplayer/Canyon.umap

(I checked, the string “Cave.umap” does not exist anywhere in the cooker log file)

Now it seems like I can hack around this in one of two ways: Either I can use the editor’s build tool in the file menu (instead of using UnrealFrontend) to build. This cooks all maps instead of specific maps, and results in my game being significantly larger on disk, or I can rename the level (I’ve tried this and it seems to work). Both of these are really annoying choices. Why would the engine not check if an asset is actually a map before trying to load it as a map? And why would the cooker choose an Engine asset over a game content umap file to cook when that asset is specified as a map on the command line?

This bug feels like an indicator of a larger bug, or at the very least, something very strange is going on with the internal map check and load functions.

Please let me know if you would like any further debugging data.

Hello JuddC,

Looking at the function you provided, I’m not seeing any spot in this code where DestinationLevelName or destUrl is being modified other than when destUrl is created. Are you sure that you’re not getting the wrong string in the first place? Could you try adding logging to the function to check the value of DestinationLevelName before anything else, and then checking destUrl immediately after it is set?

I added the log function and it does report that DestinationLevelName is just the string “Cave”.

As I said, the bug is not limited to my EnterPortal function - the cooker outright ignores the Cave map when specific maps are set for cooking on the command line (if you cook all content and don’t specify maps, the map does get included).

I went ahead and made a test project that reproduces the bug in the editor. In this test project, when you hit play in the level “Hub” (starting map), there are two level portal actors, each of which calls ACaveGameState::EnterPortal. The one labeled “Tutorial” works fine, but if you try the one labeled “Cave” it crashes.

Full log and callstack
Test project with the bug

Here’s the log that gets output before the crash:

[2017.05.22-23.04.06:279][697]PIE: Info Play in editor start time for /Game/Maps/Hub/UEDPIE_0_Hub -0.644
[2017.05.22-23.04.07:861][885]LogTemp: ACaveGameState::EnterPortal(DestinationLevelName = Cave, GameModeOverride = )
[2017.05.22-23.04.07:910][885]LogPackageName: SearchForPackageOnDisk took   0.049s to resolve Cave.
[2017.05.22-23.04.07:910][885]LogTemp: ACaveGameState::EnterPortal: ServerTravel url = /Engine/EngineSounds/ReverbSettings/Cave?Game=/Game/Blueprints/GameModes/SingleplayerGameMode.SingleplayerGameMode_C
[2017.05.22-23.04.07:915][886]LogNet: Browse: /Engine/EngineSounds/ReverbSettings/Cave?Game=/Game/Blueprints/GameModes/SingleplayerGameMode.SingleplayerGameMode_C
[2017.05.22-23.04.07:915][886]LogLoad: LoadMap: /Engine/EngineSounds/ReverbSettings/Cave?Game=/Game/Blueprints/GameModes/SingleplayerGameMode.SingleplayerGameMode_C

Thank you for the additional information. I see what you mean now and have narrowed it down to the MakeSureMapNameIsValid function itself. It takes the FString in and edits it after doing a search. The search ends up giving the wrong result. Instead of reporting this as a crash (since the crash is just from trying to load a level that doesn’t exist), I’m reporting this as an error with the function itself.

You can find and track the bug report here: UE-45335.