Skip to content

Bug: ribbon-engine-readiness-guard #503

Description

@drmoisan
  • Work Mode: full-bug

Summary

SpamBayes-dependent ribbon commands are invokable before AppItemEngines.InitAsync() has populated Globals.Engines.InboxEngines. RibbonController.SB returns null during that window, so RibbonViewer.TrainSpam_Click dereferences null and throws a NullReferenceException. The same initialization race affects every ribbon command backed by an engine in InboxEngines (Triage, Project, Context, Actionable).

Environment

  • OS/version: Windows 11, Outlook desktop (VSTO add-in host)
  • Runtime: .NET Framework 4.8, TaskMaster VSTO add-in
  • Command/flags used: Outlook Explorer ribbon, "Train Spam" button clicked immediately after add-in reload
  • Data source or fixture: Live Outlook profile; Globals.AF.Manager.Configuration still resolving

Steps to Reproduce

  1. Reload the TaskMaster add-in (or restart Outlook) so AppItemEngines.InitAsync() begins.
  2. Before InitAsync() completes, click the "Train Spam" ribbon button in the Explorer ribbon.
  3. Observe the failure in RibbonViewer.TrainSpam_Click.

Expected Behavior

Engine-dependent ribbon commands are not invokable until their backing engine in InboxEngines is available. Clicking a not-yet-ready command produces no exception; once InitAsync() completes, the commands become enabled and behave exactly as they do today.

Actual Behavior

RibbonController.SB evaluates Globals?.Engines?.InboxEngines?.TryGetValue("Spam", out var engine) against an empty ConcurrentDictionary and returns null. RibbonViewer.TrainSpam_Click then executes await Controller.SB.TrainAsync(Controller.OlSelection, true), which throws NullReferenceException. Because the handler is async void, the exception surfaces on the message-pump synchronization context rather than at the call site.

Logs / Screenshots

  • Attached minimal logs or snippet
  • Snippet:
System.NullReferenceException: Object reference not set to an instance of an object.
   at TaskMaster.RibbonViewer.TrainSpam_Click(IRibbonControl control)

Relevant source:

  • TaskMaster/Ribbon/RibbonViewer.cs (TrainSpam_Click, ~line 255-256)
  • TaskMaster/Ribbon/RibbonController.Intelligence.cs (SB property, ~line 190-202)
  • TaskMaster/AppGlobals/AppItemEngines.cs (InitAsync, InboxEngines)

Impact / Severity

  • Blocker
  • High
  • Medium
  • Low

An unhandled NullReferenceException on a routine ribbon click immediately after add-in reload. The window is short but reliably reachable, and the failure mode is a silent/unhandled async-void throw rather than a recoverable message.

Source

From: docs/features/potential/2026-08-08-ribbon-engine-readiness-guard.md

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions