dotnet/wpf · error · InvalidOperationException
SR.TextPositionIsFrozen
Error message
SR.TextPositionIsFrozen
What it means
ITextPointer.MoveByOffset on FixedTextPointer throws InvalidOperationException(SR.TextPositionIsFrozen) when the pointer was created as frozen/static. Frozen pointers are immutable snapshots (e.g. created via CreateStaticPointer) and cannot be moved.
Solutions
- Create a dynamic (non-frozen) pointer via CreateDynamicPointer and move that instead.
- Clone/duplicate the frozen pointer's position into a mutable pointer before offsetting.
- Guard movement code with a check for the pointer's frozen state.
- Catch InvalidOperationException and create a movable pointer at the same position.
Example fix
// before staticPointer.MoveByOffset(5); // throws: frozen // after var movable = container.CreateDynamicPointer(staticPointer, LogicalDirection.Forward); movable.MoveByOffset(5);
Defensive patterns
Strategy: try-catch
Validate before calling
// Guard: only call MoveByOffset on pointers you created as dynamic. bool isMovable = !(pointer is FixedTextPointer ftp && ftp.IsFrozen);
Type guard
bool IsFrozen(FixedTextPointer p) => p.IsFrozen; // check before mutating
Try / catch
try { pointer.MoveByOffset(offset); }
catch (InvalidOperationException) { var movable = container.CreateDynamicPointer(pointer, LogicalDirection.Forward); movable.MoveByOffset(offset); } Prevention
- Keep static/frozen pointers read-only; derive dynamic pointers for navigation.
- Document which APIs return frozen pointers and never mutate them.
- Centralize pointer movement behind helper methods that check freeze state.
When it happens
Trigger: Calling MoveByOffset on a FixedTextPointer obtained from CreateStaticPointer or otherwise flagged _isFrozen — e.g. static pointers from document structure queries.
Common situations: Storing static pointers for later navigation; code that treats all ITextPointers as mutable; passing a frozen pointer into APIs that adjust offsets.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- SR.NoElementObject
- SR.BadDistance
- SR.Format(SR.TextSchema_CannotSplitElement…
- SR.NotInAssociatedContainer
- SR.RowCacheCannotModifyNonExistentLayout
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/30772f01eb20ddd9.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/FixedTextPointer.cs:391
/// <see cref="ITextPointer.MoveByOffset"/>
/// </summary>
bool ITextPointer.MoveToNextContextPosition(LogicalDirection direction)
{
Debug.Assert(!_isFrozen, "Can't reposition a frozen pointer!");
ValidationHelper.VerifyDirection(direction, "direction");
Debug.Assert(!_isFrozen, "Can't reposition a frozen pointer!");
return _flowPosition.Move(direction);
}
/// <summary>
/// <see cref="ITextPointer.MoveByOffset"/>
/// </summary>
int ITextPointer.MoveByOffset(int offset)
{
if (_isFrozen) throw new InvalidOperationException(SR.TextPositionIsFrozen);
if (!_flowPosition.Move(offset))
{
throw new ArgumentException(SR.BadDistance, nameof(offset));
}
else
{
return offset;
}
}
/// <summary>
/// <see cref="ITextPointer.MoveToPosition"/>
/// </summary>
void ITextPointer.MoveToPosition(ITextPointer position)
{
FixedTextPointer ftp = this.FixedTextContainer.VerifyPosition(position);
View on GitHub (pinned to 81131a70a4)