{"record":{"id":"331e5f88a0e99b8e","repo":"RayWangQvQ/BiliBiliToolPro","slug":"iconfigurationroot-not-available-cannot-access-providers-or","errorCode":null,"errorMessage":"IConfigurationRoot not available — cannot access Providers or Reload()","messagePattern":"IConfigurationRoot not available — cannot access Providers or Reload\\(\\)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"critical","filePath":"src/Ray.BiliBiliTool.Web/Services/Pages/BiliAccount/BiliAccountPageWorkflow.cs","lineNumber":16,"sourceCode":"﻿using Microsoft.Extensions.Configuration;\nusing Ray.BiliBiliTool.Agent;\nusing Ray.BiliBiliTool.Config.SQLite;\nusing Ray.BiliBiliTool.DomainService.Dtos;\nusing Ray.BiliBiliTool.DomainService.Interfaces;\n\nnamespace Ray.BiliBiliTool.Web.Services.Pages.BiliAccount;\n\npublic class BiliAccountPageWorkflow(\n    IConfiguration configuration,\n    ILoginDomainService loginDomainService\n) : IBiliAccountPageWorkflow\n{\n    private readonly IConfigurationRoot _configurationRoot =\n        configuration as IConfigurationRoot\n        ?? throw new InvalidOperationException(\n            \"IConfigurationRoot not available — cannot access Providers or Reload()\"\n        );\n\n    public Task<List<BiliAccountDto>> GetAllAccountsAsync()\n    {\n        var cookieList = _configurationRoot.GetSection(\"BiliBiliCookies\").Get<List<string>>() ?? [];\n        var accounts = new List<BiliAccountDto>();\n\n        for (int i = 0; i < cookieList.Count; i++)\n        {\n            var cookieStr = cookieList[i];\n            var userId = ParseUserId(cookieStr);\n            accounts.Add(new BiliAccountDto(i, userId, cookieStr));\n        }\n\n        return Task.FromResult(accounts);\n    }\n","sourceCodeStart":1,"sourceCodeEnd":34,"githubUrl":"https://github.com/RayWangQvQ/BiliBiliToolPro/blob/c599b2c0da964e16ea8c454397aa07bb16212628/src/Ray.BiliBiliTool.Web/Services/Pages/BiliAccount/BiliAccountPageWorkflow.cs#L1-L34","documentation":"BiliAccountPageWorkflow's primary constructor casts the injected IConfiguration to IConfigurationRoot and throws InvalidOperationException('IConfigurationRoot not available — cannot access Providers or Reload()') when the cast fails. The workflow needs IConfigurationRoot to enumerate providers and trigger Reload() after mutating account cookies; a plain IConfiguration wrapper (e.g. a custom implementation, Options-backed, or test double) cannot support that.","triggerScenarios":"DI registration supplies an IConfiguration implementation that is not the host's ConfigurationRoot (custom IConfiguration wrapper, configuration section passed instead of the root, or a test fake) so 'configuration as IConfigurationRoot' evaluates to null.","commonSituations":"Unit/integration tests registering a mock IConfiguration; refactored hosting code that registers a custom configuration implementation; injecting a configuration section rather than the root into the workflow.","solutions":["Register the real host configuration root in DI: services.AddSingleton<IConfiguration>(hostBuilder.Configuration) where hostBuilder.Configuration is the IConfigurationRoot.","In tests, build a real ConfigurationRoot (new ConfigurationBuilder().AddInMemoryCollection(...) .Build()) instead of mocking IConfiguration.","Ensure the service resolves the root, not a section — do not pass Configuration.GetSection(...).","If a wrapper is unavoidable, implement IConfigurationRoot (expose Providers and Reload()) in the wrapper."],"exampleFix":"// before (test)\nservices.AddSingleton<IConfiguration>(new ConfigurationBuilder().Build()); // not a Root? actually Build() returns Root — wrong case: custom wrapper\nservices.AddSingleton<IConfiguration>(new FakeConfiguration());\n// after\nvar root = new ConfigurationBuilder().AddInMemoryCollection(new Dictionary<string,string>{[\"BiliBiliCookies__0\"]=\"SESSDATA=x\"}).Build();\nservices.AddSingleton<IConfiguration>(root); // root implements IConfigurationRoot","handlingStrategy":"validation","validationCode":"// before constructing the workflow\nvar root = configuration as IConfigurationRoot;\nif (root is null)\n    throw new InvalidOperationException(\"DI必须注册真正的IConfigurationRoot（hostBuilder.Configuration）\");","typeGuard":null,"tryCatchPattern":"try { workflow = new BiliAccountPageWorkflow(configuration, loginSvc); }\ncatch (InvalidOperationException ex)\n{\n    logger.LogError(ex, \"BiliAccountPageWorkflow初始化失败：配置根不可用\");\n    throw;\n}","preventionTips":["Register hostBuilder.Configuration (the root) as IConfiguration in DI","Never pass Configuration.GetSection(...) where the root is expected","In tests build a real ConfigurationBuilder().Build() root instead of mocking IConfiguration","Custom IConfiguration wrappers must implement IConfigurationRoot"],"tags":["dependency-injection","configuration","invalid-cast","blazor"],"backgroundTag":"incompatible-source-type","analyzedSha":"c599b2c0da964e16ea8c454397aa07bb16212628","analyzedAt":"2026-09-12T09:48:04.090Z","contentChangedAt":"2026-09-12T09:48:04.090Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}