Description

This report is from an EPS case:

We hit a regression upgrading our project from 5.7 to 5.8. Map Check (and any other path that ends up calling UWorldPartition::CheckForErrors) assert inside FWorldPartitionStreamingGenerator::ValidateContainerInstanceDescriptors, on the RuntimeGrid check():

for (const FGuid& ActorGuid : Cluster)
{

const FStreamingGenerationActorDescView& ActorDescView =

ContainerCollectionInstanceDescriptor.ActorDescViewMap->FindByGuidChecked(ActorGuid);

check(ActorDescView.GetRuntimeGrid() == ReferenceActorDescView.GetRuntimeGrid());

check(ActorDescView.GetIsSpatiallyLoaded() == ReferenceActorDescView.GetIsSpatiallyLoaded());

check(ActorDescView.GetContentBundleGuid() == ReferenceActorDescView.GetContentBundleGuid());

check(ActorDescView.GetExternalDataLayerAsset()== ReferenceActorDescView.GetExternalDataLayerAsset());

}

 

 

What changed between 5.7 and 5.8

Phase ordering inside PreparationPhase did not change. The mutator is still called between two

ValidateContainerInstanceDescriptors() passes. Clusters are still built in UpdateContainerDescriptor → GenerateObjectsClusters from references only. What changed is what the mutator-apply loop writes into.

 

5.7:

FContainerCollectionInstanceDescriptor::FPerInstanceData PerInstanceData =
ContainerCollectionInstanceDescriptor.GetPerInstanceData(ActorGuid);

if (ActorDescViewMutator.RuntimeGrid.IsSet())
{
    PerInstanceData.RuntimeGrid = ActorDescViewMutator.RuntimeGrid.GetValue();
}

ContainerCollectionInstanceDescriptor.AddPerInstanceData(ActorGuid, PerInstanceData);

Mutator writes a per-instance side-table. FStreamingGenerationActorDescView::GetRuntimeGrid() keeps returning the pre-mutation value, so the second ValidateContainerInstanceDescriptors pass sees a uniform grid per cluster and passes.

 

5.8 (current):

if (FStreamingGenerationActorDescView* ActorDescView =
ContainerCollectionInstanceDescriptor.ActorDescViewMap->FindByGuid(ActorGuid))
{
   if (ActorDescViewMutator.RuntimeGrid.IsSet())
   {
      ActorDescView->SetRuntimeGrid(ActorDescViewMutator.RuntimeGrid.GetValue());
   }
// ... same pattern for bIsSpatiallyLoaded, bIsHLODRelevant, HLODLayer
}

FPerInstanceData, AddPerInstanceData, GetPerInstanceData were removed; the mutator now writes the shared ActorDescView directly. The second ValidateContainerInstanceDescriptors pass now reads the post-mutation grid and trips the invariant whenever the mutator override touched only some of a ref-connected cluster.

 

Workaround:

We have made a small internal change that re-splits each ref-built cluster by the four invariant keys right after MutateContainerINstanceDescriptors, before the second validate:

  1. if (MutateContainerInstanceDescriptors(...))
    {
       SplitClustersByMutatedAttributes(); // bucket each cluster by (RuntimeGrid, bIsSpatiallyLoaded, ContentBundleGuid, ExternalDataLayerAsset)
       ValidateContainerInstanceDescriptors();
    }
    

Have Comments or More Details?

There's no existing public thread on this issue, so head over to Questions & Answers just mention UE-381148 in the post.

0
Login to Vote

Fixed
Fix Commit54431689
CreatedMay 22, 2026
ResolvedMay 25, 2026
UpdatedJun 22, 2026
View Jira Issue