stride3d/stride · error · InvalidOperationException
Height must not be infinite when virtualizing horizontally.
Error message
Height must not be infinite when virtualizing horizontally.
What it means
When VirtualizingTilePanel is oriented horizontally, MeasureOverride requires a finite available height to determine items per line. If availableSize.Height is PositiveInfinity the line layout for virtualization cannot be computed, so the panel throws InvalidOperationException rather than producing incorrect virtualization.
Solutions
- Constrain height: set explicit Height or use VerticalAlignment="Stretch" in a Grid.
- Replace the enclosing vertical StackPanel with a Grid/DockPanel that supplies a finite height.
- Scroll horizontally within a fixed-height viewport instead of letting height be unbounded.
Example fix
// before <StackPanel> <controls:VirtualizingTilePanel Orientation="Horizontal"/> </StackPanel> // after <Grid> <controls:VirtualizingTilePanel Orientation="Horizontal" VerticalAlignment="Stretch"/> </Grid>
Defensive patterns
Strategy: validation
Validate before calling
// Ensure a finite height constraint for horizontal orientation: tilePanel.Height = double.IsInfinity(desiredHeight) ? 400 : desiredHeight; // or host in a Grid with VerticalAlignment=Stretch.
Type guard
bool HasFiniteHeightConstraint(FrameworkElement el) =>
!double.IsPositiveInfinity(el.Height) || el.VerticalAlignment == VerticalAlignment.Stretch; Try / catch
try { panelHost.UpdateLayout(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("Height must not be infinite")) { tilePanel.Height = 400; tilePanel.UpdateLayout(); } Prevention
- Never place horizontally-oriented virtualizing tile panels inside vertical StackPanels.
- Use Grid rows with fixed/star sizes rather than Auto when hosting the panel.
- Check ancestor ScrollViewers for vertical auto-scroll settings that yield infinite height.
When it happens
Trigger: A horizontally-oriented VirtualizingTilePanel measured with infinite height: inside a vertical StackPanel, a ScrollViewer with VerticalScrollBarVisibility=Auto, or an unconstrained Grid Auto row.
Common situations: Vertical StackPanel wrapper around a horizontal tile list; auto-sized rows/cells; forgetting to set Height or VerticalAlignment when embedding the panel.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- Width must not be infinite when virtualizing vertically.
- Unable to reach the ItemsPresenter of the associated…
- BringItemToView cannot be used when the tree view is…
- entity must contain a non-null asset entity.
- A dispatcher lock must be created from a different thread…
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/bd8cf535592ac66e.
Report an issue: GitHub.
Appendix: source
Thrown at sources/presentation/Stride.Core.Presentation.Wpf/Controls/VirtualizingTilePanel.cs:169
ItemCount = parentItemsControl.Items.Count;
ItemsPerLine = ItemCount;
lineCount = ItemsPerLine;
Size desiredSize;
if (Orientation == Orientation.Vertical)
{
if (double.IsPositiveInfinity(availableSize.Width))
throw new InvalidOperationException("Width must not be infinite when virtualizing vertically.");
ItemsPerLine = (int)Math.Ceiling(availableSize.Width - MinimumItemSpacing) / (int)(ItemSlotSize.Width + MinimumItemSpacing);
ItemsPerLine = Math.Max(1, Math.Min(ItemsPerLine, ItemCount));
lineCount = ComputeLineCount(ItemCount);
desiredSize = new Size(availableSize.Width, lineCount * ItemSlotSize.Height);
}
else
{
if (double.IsPositiveInfinity(availableSize.Height))
throw new InvalidOperationException("Height must not be infinite when virtualizing horizontally.");
ItemsPerLine = (int)Math.Ceiling(availableSize.Height - MinimumItemSpacing) / (int)Math.Ceiling(ItemSlotSize.Height + MinimumItemSpacing);
ItemsPerLine = Math.Max(1, Math.Min(ItemsPerLine, ItemCount));
lineCount = ComputeLineCount(ItemCount);
desiredSize = new Size(lineCount * ItemSlotSize.Width, availableSize.Height);
}
UpdateScrollInfo(availableSize);
int firstVisibleItemIndex, lastVisibleItemIndex;
GetVisibilityRange(availableSize, out firstVisibleItemIndex, out lastVisibleItemIndex);
// Get the generator position of the first visible data item
var startPos = generator.GeneratorPositionFromIndex(firstVisibleItemIndex);
var childIndex = (startPos.Offset == 0) ? startPos.Index : startPos.Index + 1;
using (generator.StartAt(startPos, GeneratorDirection.Forward, true))View on GitHub (pinned to 96fad776d2)