Windows 10 Pro x64, 10.0.19045, with Windows.UI.Xaml.dll version 10.0.19041.6456.
Other software
No third-party shell integration or privilege-management product has been identified in the crashing path. The foreground shell happens to be cmd.exe, but the faulting process is WindowsTerminal.exe, not cmd.exe.
Steps to reproduce
This is timing-dependent, but it has now occurred three times on the same machine:
Open a Windows Terminal window with multiple active tabs.
Produce sustained, high-volume output so that the terminal is actively rendering and has substantial scrollback.
Begin dragging a tab.
Move the dragged tab over the terminal content area, particularly while the UI is under load or while moving toward another window/tab strip.
Windows Terminal may terminate immediately, taking every tab in that window/process with it.
The crash happens during DragOver; dropping the tab is not required. Lower UI load makes the issue much less frequent.
Expected behavior
Dragging/reordering/tearing out a tab must not terminate Windows Terminal. An internal tab drag that passes over terminal content should not be treated as an external file/text drop.
Actual behavior
The whole WindowsTerminal.exe process exits without a user-facing error. All tabs hosted by that process disappear.
Three observed incidents have the same Event Viewer signature:
PROCESS_NAME: WindowsTerminal.exe
ERROR_CODE: 0xc000027b - An application-internal exception has occurred.
FAILURE_BUCKET_ID:
STOWED_EXCEPTION_c000027b_Windows.UI.Xaml.dll!
CXcpDispatcher::OnReentrancyProtectedWindowMessage
IMAGE_NAME: Windows.UI.Xaml.dll
IMAGE_VERSION: 10.0.19041.6456
The fail-fast HRESULT passed to RaiseFailFastException is 0x8000ffff
(E_UNEXPECTED / Catastrophic failure).
The dump analysis showed peak commit in the approximately 594-630 MB range. There is no out-of-memory exception and no renderer/AtlasEngine frame in the failing path.
Full symbolized failing-thread stack
This is the representative fully symbolized stack from the same recurring 0xc000027b, Windows.UI.Xaml.dll+0x481782 signature. It captures the entire nested call from the fail-fast down through TermControl::_DragOverHandler, the XAML drag-over event, and the outer COM drag operation:
DataView() enters DataExchange!DropTargetInternal::DragInfo::get_Data, which performs a synchronous cross-apartment COM request.
Because this is an STA call, COM enters CCliModalLoop and pumps window messages while waiting for the request.
The nested message pump dispatches pending XAML work through CDeferredInvoke::DispatchQueuedMessage.
That queued work re-enters CXcpDispatcher::OnReentrancyProtectedWindowMessage while the original XAML drag dispatch is still active.
XAML detects the prohibited reentrancy and deliberately fail-fasts with E_UNEXPECTED (0x8000ffff), surfaced by WER as 0xc000027b.
This is not a cmd.exe crash, an out-of-memory failure, or the Atlas renderer/history-buffer crash fixed elsewhere. The immediate unsafe operation is the synchronous e.DataView() getter during DragOver.
High output/large scrollback appears to be a timing amplifier, not the direct corrupt object. Under heavy output, XAML has more deferred render/layout/scroll work available for the COM modal loop to dispatch, increasing the chance of prohibited nested dispatch. That interpretation is consistent with the stack and repeatability, but it should be treated as a timing hypothesis until confirmed with instrumentation.
Current source path
The crashing release and current main contain materially the same handler in src/cascadia/TerminalControl/TermControl.cpp:
void TermControl::_DragOverHandler(..., const DragEventArgs& e)
{
if (_IsClosing())
{
return;
}
if (!(e.DataView().Contains(StandardDataFormats::StorageItems()) ||
e.DataView().Contains(StandardDataFormats::Text())))
{
return;
}
e.AcceptedOperation(DataPackageOperation::Copy);
if (e.DataView().Contains(StandardDataFormats::StorageItems()))
{
...
}
else if (e.DataView().Contains(StandardDataFormats::Text()))
{
...
}
}
This evaluates the synchronous DataView() getter up to four times for one drag-over callback. The representative crash occurs at _DragOverHandler+0x3b, during the first getter evaluation.
Internal tab drags already place private windowId and pid properties into their data package in TerminalPage::_onTabDragStarting. They are unrelated to the file/text drop support in TermControl, so allowing the routed event to reach the terminal content handler creates unnecessary exposure to this synchronous payload retrieval.
Suggested mitigation/fix
The safest Terminal-side mitigation is to prevent internal tab drags from entering the terminal content drop handler at all:
Set an internal-tab-drag-in-progress flag at TabDragStarting and clear it on every completion/cancel/drop-outside path.
Before calling e.DataView(), have TermControl::_DragOverHandler return immediately when that flag is set; alternatively, temporarily set AllowDrop=false on terminal controls for the lifetime of an internal tab drag.
Preserve existing tab-strip handling for moving tabs between windows.
For external file/text drags, cache const auto dataView = e.DataView() rather than evaluating the getter repeatedly.
Consider moving external payload inspection out of high-frequency DragOver where possible and into Drop/an asynchronous path.
A time-based throttle/debounce is not a complete fix: the first DataView() call can trigger the fail-fast. A C++ try/catch around e.DataView() is also unlikely to contain this failure because XAML calls RaiseFailFastException from the nested dispatcher before the getter returns.
Acceptance criteria
Add a focused RED reproduction/stress test or diagnostic harness that performs internal tab drags across terminal content while output is continuously updating; demonstrate that it can exercise the unsafe path before the fix and no longer does afterward.
Internal tab drag/reorder/tear-out never invokes TermControl::_DragOverHandler's DataView() payload retrieval.
Repeated internal tab drags across terminal content under heavy output do not produce 0xc000027b / Windows.UI.Xaml.dll+0x481782 on Windows 10 19045.
Cross-window tab movement, same-window tab reordering, and tab tear-out continue to work.
External file and text drop into terminal content continue to work.
The fix does not rely only on notification throttling or exception handling around a fail-fast path.
Related issues
#18719 is an exact prior match: tab drag on Windows 10, 0xc000027b, Windows.UI.Xaml.dll, and the same fault offset 0x481782. It was closed by the stale bot after the original reporter could not provide the requested dump. The full dumps described here provide the missing evidence.
Additional triage notes
This is distinct from #20366, which fixed a c0000005 crash in AtlasEngine::PaintCursor associated with heavy buffers/tab merging. There is no AtlasEngine frame here, and the failure code/bucket differ.
This is distinct from #19026, which guards a null storage-item result after dropping a relative path. This crash occurs during DragOver, before a drop payload is consumed.
The current main handler still performs the same synchronous DataView() calls, so no available Terminal update appears to contain a fix as of 2026-08-05.
Dump availability and privacy
Two full user-mode dumps are available privately to the Terminal maintainers. They are approximately 806 MB and 852 MB. They should not be attached publicly because full Terminal dumps may contain terminal buffer contents, command lines, environment data, and other sensitive information.