AvaloniaUI/Avalonia · error · ArgumentOutOfRangeException
{nameof(textLength)} ('0') must be a non-zero value.
Error message
{nameof(textLength)} ('0') must be a non-zero value. What it means
Thrown by TextLineImpl.GetTextBounds when textLength is exactly zero. GetTextBounds computes the bounding rectangles for a range of characters within a formatted text line; a zero-length range has no meaningful bounds, so Avalonia rejects it outright. The caller must request a non-zero character span.
Source
Thrown at src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs:677
break;
}
if (nextRun is DrawableTextRun nextDrawable)
{
directionalWidth += nextDrawable.Size.Width;
}
lastRunIndex = nextIndexedRun.RunIndex;
}
return lastRunIndex;
}
public override IReadOnlyList<TextBounds> GetTextBounds(int firstTextSourceIndex, int textLength)
{
if (textLength == 0)
{
throw new ArgumentOutOfRangeException(nameof(textLength), textLength, $"{nameof(textLength)} ('0') must be a non-zero value. ");
}
if (_indexedTextRuns is null || _indexedTextRuns.Count == 0)
{
return [];
}
var currentPosition = FirstTextSourceIndex;
var remainingLength = textLength;
//We can return early if the requested text range is before the line's text range.
if (firstTextSourceIndex + textLength < FirstTextSourceIndex)
{
var indexedTextRun = _indexedTextRuns[0];
var currentDirection = GetRunDirection(indexedTextRun.TextRun, _resolvedFlowDirection);
return [new TextBounds(new Rect(0, 0, 0, Height), currentDirection, [])];
}View on GitHub (pinned to 11c5427268)
Solutions
- Guard the call site: if (textLength == 0) return an empty bounds list instead of calling GetTextBounds.
- Ensure the computed textLength is always at least 1 when a real range is intended.
- If performing caret hit-testing with a degenerate (empty) selection, skip the GetTextBounds call entirely.
Example fix
// before
var bounds = line.GetTextBounds(startIndex, endIndex - startIndex); // throws when equal
// after
var length = endIndex - startIndex;
var bounds = length > 0
? line.GetTextBounds(startIndex, length)
: Array.Empty<TextBounds>(); Defensive patterns
Strategy: validation
Validate before calling
static IReadOnlyList<TextBounds> SafeGetBounds(TextLine line, int first, int len)
{
if (len <= 0) return Array.Empty<TextBounds>();
return line.GetTextBounds(first, len);
} Prevention
- Clamp computed text lengths to a minimum of 1 before calling GetTextBounds.
- Skip bounds queries for degenerate (zero-length) selections.
- Centralize selection-length computation to avoid raw subtraction at call sites.
When it happens
Trigger: Calling textLine.GetTextBounds(firstTextSourceIndex, 0) — i.e. passing a textLength of zero to an already-formatted TextLine instance. Common when the length is computed from a subtraction that yields zero, or when a measurement routine is called with an empty selection range.
Common situations: Text selection/caret-hit-testing code that computes length as (end - start) and passes it through without clamping; caret positioned at start==end producing a zero-length bounds request; automated layout passes that probe with zero-length ranges.
Related errors
- Invalid {nameof(TextRunProperties.FontRenderingEmSize)}
- Font weight must be > 0.
- Font stretch must be > 1.
- Duration value cannot be negative.
- DelayBetweenIterations value cannot be negative.
AI-assisted analysis of AvaloniaUI/Avalonia@11c5427268 (2026-08-13).
Data as JSON: /api/errors/fea124e752207bb8.
Report an issue: GitHub.