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
- Clamp offsets to [0, TextContainer.IMECharCount] before passing to TSF interop if you drive the store yourself.
- Catch ArgumentException and recompute offsets after text changed events.
- Update the IME driver / WPF version; specific stale-offset IME bugs were addressed in servicing.
- 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
- Clamp TSF offsets to document length
- Avoid editing text during active composition
- Test with third-party IMEs and rapid edits
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 ofView on GitHub (pinned to 81131a70a4)