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:
if (MutateContainerInstanceDescriptors(...))
{
SplitClustersByMutatedAttributes(); // bucket each cluster by (RuntimeGrid, bIsSpatiallyLoaded, ContentBundleGuid, ExternalDataLayerAsset)
ValidateContainerInstanceDescriptors();
}
There's no existing public thread on this issue, so head over to Questions & Answers just mention UE-381148 in the post.
| 0 |
| Component | UE - World Creation - Worldbuilding Tools - World Partition |
|---|---|
| Affects Versions | 5.8 |
| Target Fix | 5.8 |
| Fix Commit | 54431689 |
|---|
| Created | May 22, 2026 |
|---|---|
| Resolved | May 25, 2026 |
| Updated | Jun 22, 2026 |