{"record":{"id":"cb14a019f1af36f9","repo":"microsoft/ailab","slug":"botframeworkoptions-must-be-configured-prior-to-setting-up","errorCode":null,"errorMessage":"BotFrameworkOptions must be configured prior to setting up the State Accessors","messagePattern":"BotFrameworkOptions must be configured prior to setting up the State Accessors","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"BuildAnIntelligentBot/src/ChatBot/Startup.cs","lineNumber":119,"sourceCode":"\n      var userState = new UserState(dataStore);\n      services.AddSingleton(userState);\n\n      // Add the personality chat middleware\n\n      // Add the translator speech middleware\n\n      services.AddTransient<IBot, EchoBot>();\n\n      // Create and register state accessors.\n      // Accessors created here are passed into the IBot-derived class on every turn.\n      services.AddSingleton(sp =>\n      {\n        // We need to grab the conversationState we added on the options in the previous step\n        var options = sp.GetRequiredService<IOptions<BotFrameworkOptions>>().Value;\n        if (options == null)\n        {\n          throw new InvalidOperationException(\"BotFrameworkOptions must be configured prior to setting up the State Accessors\");\n        }\n\n        // Create the custom state accessor.\n        // State accessors enable other components to read and write individual properties of state.\n        var accessors = new EchoBotAccessors(conversationState, userState)\n        {\n          // Initialize Dialog State\n          ReservationState = userState.CreateProperty<ReservationData>(\"ReservationState\"),\n        };\n\n        return accessors;\n      });\n\n      // Add QnA Maker here\n    }\n\n    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)\n    {","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/microsoft/ailab/blob/89fe2fc62081145ec5408d42059cbcb7c4a033c8/BuildAnIntelligentBot/src/ChatBot/Startup.cs#L101-L137","documentation":"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.","triggerScenarios":"Calling Configure order wrong: registering the state-accessor singleton before services.AddBot(options => ...), or omitting AddBot entirely so BotFrameworkOptions is never registered/populated.","commonSituations":"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.","solutions":["Ensure services.AddBot<EchoBot>(options => { ... options.ConversationState = ...; }) is called BEFORE the state accessor singleton registration in ConfigureServices","Keep registration order: AddBot first, then AddSingleton for EchoBotAccessors","If upgraded from an older SDK, follow the v4 template Startup.cs and add ConversationState/UserState inside the AddBot options lambda"],"exampleFix":"// before\nservices.AddSingleton(sp => { ... accessors ... });\nservices.AddBot<EchoBot>(options => { });\n// after\nservices.AddBot<EchoBot>(options => {\n  options.ConversationState = new ConversationState(new MemoryStorage());\n});\nservices.AddSingleton(sp => { ... accessors ... });","handlingStrategy":"validation","validationCode":"var botOptions = services.BuildServiceProvider().GetService<IOptions<BotFrameworkOptions>>();\nif (botOptions?.Value == null)\n    throw new InvalidOperationException(\"Call services.AddBot(...) before registering state accessors\");","typeGuard":null,"tryCatchPattern":"try\n{\n    services.AddSingleton(sp =>\n    {\n        var options = sp.GetRequiredService<IOptions<BotFrameworkOptions>>().Value;\n        if (options == null) throw new InvalidOperationException(\"BotFrameworkOptions must be configured first\");\n        return new EchoBotAccessors(conversationState, userState);\n    });\n}\ncatch (InvalidOperationException ex)\n{\n    logger.LogError(ex, \"Startup registration order error\");\n    throw;\n}","preventionTips":["Keep ConfigureServices registration order: AddBot first, then dependent singletons","Follow the official v4 template Startup.cs as a reference for ordering","Add a comment near the accessor registration warning it depends on AddBot","Review registration order after any SDK upgrade or refactor"],"tags":["csharp","aspnetcore","botframework","startup-order"],"backgroundTag":"invalid-state-transition","analyzedSha":"89fe2fc62081145ec5408d42059cbcb7c4a033c8","analyzedAt":"2026-09-13T20:10:53.835Z","contentChangedAt":"2026-09-13T20:10:53.835Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}