{"record":{"id":"42611e8450bed454","repo":"Hmbown/CodeWhale","slug":"active-plugin-registry-is-missing-its-pre-dotenv-e","errorCode":null,"errorMessage":"active plugin registry is missing its pre-dotenv environment snapshot","messagePattern":"active plugin registry is missing its pre-dotenv environment snapshot","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/mcp.rs","lineNumber":5437,"sourceCode":"fn merge_plugin_mcp_servers(\n    config: McpConfig,\n    registry: &crate::plugins::PluginRegistry,\n) -> Result<McpConfig> {\n    let Some(state_path) = registry.state_path().map(Path::to_path_buf) else {\n        return Ok(config);\n    };\n    let plugins = registry\n        .active_plugins()\n        .into_iter()\n        .filter_map(|plugin| {\n            plugin\n                .authority(state_path.clone(), registry.workspace().to_path_buf())\n                .map(|authority| (plugin.name().to_string(), plugin.clone(), authority))\n        })\n        .collect::<Vec<_>>();\n\n    let host_environment = registry.host_environment().ok_or_else(|| {\n        anyhow::anyhow!(\"active plugin registry is missing its pre-dotenv environment snapshot\")\n    })?;\n    merge_plugin_mcp_servers_from_plugins_with_environment(config, plugins, host_environment)\n}\n\nfn merge_plugin_mcp_servers_from_plugins_with_environment(\n    mut config: McpConfig,\n    plugins: impl IntoIterator<\n        Item = (\n            String,\n            crate::plugins::types::LoadedPlugin,\n            crate::plugins::types::PluginAuthority,\n        ),\n    >,\n    host_environment: Arc<crate::plugins::HostEnvironment>,\n) -> Result<McpConfig> {\n    for (plugin_name, plugin, authority) in plugins {\n        // Adapter-level denial keeps headless paths fail-closed even if a\n        // future caller accidentally passes the full inventory instead of the","sourceCodeStart":5419,"sourceCodeEnd":5455,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/mcp.rs#L5419-L5455","documentation":"When merging plugin-provided MCP servers into the config, the code needs the plugin registry's captured pre-dotenv environment snapshot (the host environment as it was before .env loading). If the active registry has none, merging cannot proceed safely and fails with this error instead of silently using a wrong environment.","triggerScenarios":"Calling the plugin MCP merge path when registry.host_environment() returns None — i.e. the registry was constructed without capturing the environment snapshot before dotenv was applied.","commonSituations":"Plugin registry initialized by an alternate entry point that skipped the snapshot; a refactor changed registry construction order so the env capture no longer happens before dotenv loads.","solutions":["Ensure the plugin registry is constructed via the standard path that captures host_environment() before dotenv loading","Fix initialization order: capture the environment snapshot before any .env file is applied","If constructing a registry manually, supply the host environment snapshot explicitly"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// ensure the registry captured its environment snapshot before merging\nanyhow::ensure!(\n    registry.host_environment().is_some(),\n    \"plugin registry built without pre-dotenv env snapshot\"\n);","typeGuard":null,"tryCatchPattern":"match merge_plugin_mcp_servers(config) {\n    Err(e) if e.to_string().contains(\"pre-dotenv environment snapshot\") => rebuild_registry_with_env_snapshot_then_retry(),\n    other => other,\n}","preventionTips":["Always construct the plugin registry through the standard initialization path","Capture the host environment before applying any .env files","Add an invariant test that host_environment() is Some after normal init"],"tags":["mcp","plugins","environment","invariant"],"backgroundTag":"missing-env-var","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}