dotnet/wpf · error · ArgumentException

SR.TextStore_BadIMECharOffset

Error message

SR.TextStore_BadIMECharOffset

What it means

ValidateCharOffset throws ArgumentException when a character offset supplied (typically by the TSF/cicero text service) is negative or greater than the text container's IMECharCount. Cicero sometimes sends offsets beyond the document extent (bug 1395082), and WPF rejects them rather than corrupting the text tree.

Solutions

  1. Clamp offsets to [0, TextContainer.IMECharCount] before passing to TSF interop if you drive the store yourself.
  2. Catch ArgumentException and recompute offsets after text changed events.
  3. Update the IME driver / WPF version; specific stale-offset IME bugs were addressed in servicing.
  4. Synchronize edits with composition: avoid programmatic text changes while an IME composition is active.

Example fix

// before
int offset = GetImeOffset(); // may exceed document
ValidateCharOffset(offset);
// after
int offset = Math.Clamp(GetImeOffset(), 0, textContainer.IMECharCount);
ValidateCharOffset(offset);
Defensive patterns

Strategy: validation

Validate before calling

bool offsetValid = offset >= 0 && offset <= textContainer.IMECharCount;

Type guard

bool IsValidCharOffset(int offset, ITextContainer c) => offset >= 0 && offset <= c.IMECharCount;

Try / catch

try { ValidateCharOffset(offset); }
catch (ArgumentException) { offset = Math.Clamp(offset, 0, textContainer.IMECharCount); }

Prevention

When it happens

Trigger: TSF calls into TextStore with an offset (e.g. for composition start/adproperty queries) where offset < 0 || offset > TextContainer.IMECharCount.

Common situations: Third-party IMEs computing offsets against stale text; rapid edits shrinking the document while the IME still references old offsets; bug-triggering timing races noted in WPF bug 1395082.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/e1ea386400a5cfb8. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/TextStore.cs:3332

        // Asserts that this TextStore is sending TS_TEXTCHANGE structs
        // in sync with the actual TextContainer.
        private void VerifyTextStoreConsistency()
        {
            if (_netCharCount != this.TextContainer.IMECharCount)
            {
                Invariant.Assert(false, "TextContainer/TextStore have inconsistent char counts!");
            }
        }

        // Validates the character offset supplied by cicero.
        // See bug 1395082.  Sometimes cicero gives us offsets that are
        // too large for the document.
        private void ValidateCharOffset(int offset)
        {
            if (offset < 0 || offset > this.TextContainer.IMECharCount)
            {
                throw new ArgumentException(SR.Format(SR.TextStore_BadIMECharOffset, offset, this.TextContainer.IMECharCount));
            }
        }

        /// Discards previous composition undo unit, to prevent
        /// from merging it with the subsequent typing.
        private void BreakTypingSequence(ITextPointer caretPosition)
        {
            CompositionParentUndoUnit unit = PeekCompositionParentUndoUnit();

            // We also put the caret at the end of the composition after
            // redoing a composition undo.  So update the end position now.
            unit?.RecordRedoSelectionState(caretPosition, caretPosition);
        }

        // Repositions an ITextRange to comply with limitations on IME input.
        // We cannot modify Table structure, or insert content
        // before or after Tables or BlockUIContainers while maintaing our
        // contract with the cicero interfaces (without major refactoring of

View on GitHub (pinned to 81131a70a4)