microsoft/ailab · error · InvalidOperationException

BotFrameworkOptions must be configured prior to setting up…

Error message

BotFrameworkOptions must be configured prior to setting up the State Accessors

What it means

This guard runs in a singleton factory that builds EchoBotAccessors from the registered BotFrameworkOptions. If IOptions<BotFrameworkOptions> resolves to null, the Bot Framework services (including ConversationState stored in options) were never configured via services.AddBot(...), so the accessors cannot find conversationState. The code throws InvalidOperationException to fail fast at startup.

Solutions

  1. Ensure services.AddBot<EchoBot>(options => { ... options.ConversationState = ...; }) is called BEFORE the state accessor singleton registration in ConfigureServices
  2. Keep registration order: AddBot first, then AddSingleton for EchoBotAccessors
  3. If upgraded from an older SDK, follow the v4 template Startup.cs and add ConversationState/UserState inside the AddBot options lambda

Example fix

// before
services.AddSingleton(sp => { ... accessors ... });
services.AddBot<EchoBot>(options => { });
// after
services.AddBot<EchoBot>(options => {
  options.ConversationState = new ConversationState(new MemoryStorage());
});
services.AddSingleton(sp => { ... accessors ... });
Defensive patterns

Strategy: validation

Validate before calling

var botOptions = services.BuildServiceProvider().GetService<IOptions<BotFrameworkOptions>>();
if (botOptions?.Value == null)
    throw new InvalidOperationException("Call services.AddBot(...) before registering state accessors");

Try / catch

try
{
    services.AddSingleton(sp =>
    {
        var options = sp.GetRequiredService<IOptions<BotFrameworkOptions>>().Value;
        if (options == null) throw new InvalidOperationException("BotFrameworkOptions must be configured first");
        return new EchoBotAccessors(conversationState, userState);
    });
}
catch (InvalidOperationException ex)
{
    logger.LogError(ex, "Startup registration order error");
    throw;
}

Prevention

When it happens

Trigger: Calling Configure order wrong: registering the state-accessor singleton before services.AddBot(options => ...), or omitting AddBot entirely so BotFrameworkOptions is never registered/populated.

Common situations: Reordering ConfigureServices after refactoring; copying a partial Startup.cs sample; removing the AddBot call during an SDK upgrade (Bot Builder v3 to v4 migration); options registered but ConversationState never added to options.

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 microsoft/ailab@89fe2fc620 (2026-09-13). Data as JSON: /api/errors/cb14a019f1af36f9. Report an issue: GitHub.

Appendix: source

Thrown at BuildAnIntelligentBot/src/ChatBot/Startup.cs:119

      var userState = new UserState(dataStore);
      services.AddSingleton(userState);

      // Add the personality chat middleware

      // Add the translator speech middleware

      services.AddTransient<IBot, EchoBot>();

      // Create and register state accessors.
      // Accessors created here are passed into the IBot-derived class on every turn.
      services.AddSingleton(sp =>
      {
        // We need to grab the conversationState we added on the options in the previous step
        var options = sp.GetRequiredService<IOptions<BotFrameworkOptions>>().Value;
        if (options == null)
        {
          throw new InvalidOperationException("BotFrameworkOptions must be configured prior to setting up the State Accessors");
        }

        // Create the custom state accessor.
        // State accessors enable other components to read and write individual properties of state.
        var accessors = new EchoBotAccessors(conversationState, userState)
        {
          // Initialize Dialog State
          ReservationState = userState.CreateProperty<ReservationData>("ReservationState"),
        };

        return accessors;
      });

      // Add QnA Maker here
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {

View on GitHub (pinned to 89fe2fc620)