dotnet/wpf · warning · COMException

SR.TextStore_NoSink

Error message

SR.TextStore_NoSink

What it means

RequestLock, part of the TSF ITextStoreACP contract, asks the sink for a document lock. If no sink has ever been advised (HasSink is false), the store throws COMException SR.TextStore_NoSink because there is no one to request the lock from. This indicates RequestLock was invoked without a preceding successful AdviseSink.

Solutions

  1. Ensure the text control is focused and TSF connection completed (AdviseSink succeeded) before input/IME activity; refocus the control to re-establish the sink
  2. Delay or guard IME-dependent operations until the store has an active sink
  3. Disable faulty third-party TSF/IME components that call RequestLock out of order
  4. Environmental HRESULT to TSF; typically no app-level catch needed, but log it if IME input breaks
Defensive patterns

Strategy: try-catch

Try / catch

try { /* IME-driven path */ } catch (COMException ce) when (ce.Message.Contains("NoSink") || (uint)ce.ErrorCode == 0xFFFFFFFF) { RefocusTextControl(); }

Prevention

When it happens

Trigger: TSF/IME calling RequestLock on the TextStore before (or after) the ITextStoreACPSink was advised/unadvised — e.g. lock request arriving during connection setup, after teardown, or when AdviseSink failed earlier (see CONNECT_E errors).

Common situations: IME composition starting before TSF finished advising the sink; focus races between window activation and text store registration; third-party TSF services making out-of-order calls.

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


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

Appendix: source

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

        {
            if (obj != _sink)
            {
                throw new COMException(SR.TextStore_CONNECT_E_NOCONNECTION, unchecked((int)0x80040200));
            }

            Marshal.ReleaseComObject(_sink);
            _sink = null;

            // We don't need to track window movement for this textstore any more.
            // _sink was the only consumer.
            _textservicesHost.UnregisterWinEventSink(this);
        }

        // See msdn's ITextStoreACP documentation for a full description.
        public void RequestLock(UnsafeNativeMethods.LockFlags flags, out int hrSession)
        {
            if (!HasSink)
                throw new COMException(SR.TextStore_NoSink);

            if (flags == 0)
                throw new COMException(SR.TextStore_BadLockFlags);

            bool isReplayingIMEChanges =  (_replayingIMEChangeReentrancyCount > 0);

            if (IsTracing)
            {
                IMECompositionTracer.Trace(this, IMECompositionTraceOp.BRequestLock,
                                            "f:", flags,
                                            "lf:", _lockFlags,
                                            "icr:", _replayingIMEChangeReentrancyCount,
                                            "ric:", isReplayingIMEChanges,
                                            "tcr:", _textChangeReentrencyCount,
                                            "paf:", _pendingAsyncLockFlags);
                if (_replayingIMEChangeReentrancyCount != 0)
                {
                    IMECompositionTracer.Mark(new System.Diagnostics.StackTrace(true));

View on GitHub (pinned to 81131a70a4)