Summary
RibbonViewer.SpamBayesEnabled_Click and RibbonViewer.TriageEnabled_Click are void methods whose body is an unawaited call to Controller.Engines.ToggleEngineAsync(...). The returned Task is discarded, so the toggle completes asynchronously with no ordering guarantee and any exception it raises is swallowed into an unobserved task.
Environment
- OS/version: Windows 11, Outlook desktop (VSTO add-in host)
- Runtime: .NET Framework 4.8.1, TaskMaster VSTO add-in
- Command/flags used: Outlook Explorer ribbon, Spam Manager and Triage configuration menus
- Data source or fixture: Live Outlook profile
Steps to Reproduce
- Open Outlook with the TaskMaster add-in loaded.
- Click the "SpamBayes Enabled" toggle button (or "Triage Enabled").
- Observe that the caller returns before
ToggleEngineAsync has awaited Globals.AF.Manager.Configuration and flipped ClassifierActivated.
- Induce a failure inside the configuration load and observe that no error is surfaced.
Expected Behavior
The toggle either completes before the handler returns, or the handler is async void with an explicit await and a boundary try/catch that reports the failure through the project logging pattern. Either way an exception is observed and logged rather than discarded.
Actual Behavior
public void SpamBayesEnabled_Click(Office.IRibbonControl control, bool pressed) =>
Controller.Engines.ToggleEngineAsync(SpamBayes.GroupName);
public void TriageEnabled_Click(Office.IRibbonControl control, bool pressed) =>
Controller.Engines.ToggleEngineAsync("Triage");
(TaskMaster/Ribbon/RibbonViewer.cs, Spam Config and Triage Config regions.)
ToggleEngineAsync awaits Globals.AF.Manager.Configuration before mutating loader.Config.ClassifierActivated, so the state change is genuinely deferred. The discarded Task means a faulted toggle is silently lost; the user sees no error and the setting simply does not change.
The sibling handlers in the same regions (SpamSaveNetwork_Click, SpamSaveLocal_Click, TriageSaveNetwork_Click, TriageSaveLocal_Click) are correctly written as async void with await, which makes these two an inconsistency rather than a deliberate pattern.
Logs / Screenshots
Impact / Severity
The happy path usually works because the configuration task is typically already complete by the time a user reaches the configuration menu. The defect is the swallowed failure and the absent ordering guarantee, not a routinely-observed break.
Source
From: docs/features/potential/2026-08-08-ribbon-toggle-engine-fire-and-forget.md
Summary
RibbonViewer.SpamBayesEnabled_ClickandRibbonViewer.TriageEnabled_Clickarevoidmethods whose body is an unawaited call toController.Engines.ToggleEngineAsync(...). The returnedTaskis discarded, so the toggle completes asynchronously with no ordering guarantee and any exception it raises is swallowed into an unobserved task.Environment
Steps to Reproduce
ToggleEngineAsynchas awaitedGlobals.AF.Manager.Configurationand flippedClassifierActivated.Expected Behavior
The toggle either completes before the handler returns, or the handler is
async voidwith an explicitawaitand a boundarytry/catchthat reports the failure through the project logging pattern. Either way an exception is observed and logged rather than discarded.Actual Behavior
(
TaskMaster/Ribbon/RibbonViewer.cs, Spam Config and Triage Config regions.)ToggleEngineAsyncawaitsGlobals.AF.Manager.Configurationbefore mutatingloader.Config.ClassifierActivated, so the state change is genuinely deferred. The discardedTaskmeans a faulted toggle is silently lost; the user sees no error and the setting simply does not change.The sibling handlers in the same regions (
SpamSaveNetwork_Click,SpamSaveLocal_Click,TriageSaveNetwork_Click,TriageSaveLocal_Click) are correctly written asasync voidwithawait, which makes these two an inconsistency rather than a deliberate pattern.Logs / Screenshots
Impact / Severity
The happy path usually works because the configuration task is typically already complete by the time a user reaches the configuration menu. The defect is the swallowed failure and the absent ordering guarantee, not a routinely-observed break.
Source
From: docs/features/potential/2026-08-08-ribbon-toggle-engine-fire-and-forget.md