Hmbown/CodeWhale · error
active plugin registry is missing its pre-dotenv environment
Error message
active plugin registry is missing its pre-dotenv environment snapshot
What it means
When merging plugin-contributed MCP servers, the manager needs the process environment as it was before any dotenv/.env overlays were applied, so plugin servers get the host environment rather than project-scoped values. That snapshot (registry.host_environment()) is captured when the plugin registry is built; if it is absent the merge fails on this invariant instead of silently using the wrong environment.
Source
Thrown at crates/tui/src/mcp.rs:3657
fn merge_plugin_mcp_servers(
config: McpConfig,
registry: &crate::plugins::PluginRegistry,
) -> Result<McpConfig> {
let Some(state_path) = registry.state_path().map(Path::to_path_buf) else {
return Ok(config);
};
let plugins = registry
.active_plugins()
.into_iter()
.filter_map(|plugin| {
plugin
.authority(state_path.clone(), registry.workspace().to_path_buf())
.map(|authority| (plugin.name().to_string(), plugin.clone(), authority))
})
.collect::<Vec<_>>();
let host_environment = registry.host_environment().ok_or_else(|| {
anyhow::anyhow!("active plugin registry is missing its pre-dotenv environment snapshot")
})?;
merge_plugin_mcp_servers_from_plugins_with_environment(config, plugins, host_environment)
}
fn merge_plugin_mcp_servers_from_plugins_with_environment(
mut config: McpConfig,
plugins: impl IntoIterator<
Item = (
String,
crate::plugins::types::LoadedPlugin,
crate::plugins::types::PluginAuthority,
),
>,
host_environment: Arc<crate::plugins::HostEnvironment>,
) -> Result<McpConfig> {
for (plugin_name, plugin, authority) in plugins {
// Adapter-level denial keeps headless paths fail-closed even if a
// future caller accidentally passes the full inventory instead of theView on GitHub (pinned to 8880682c63)
Solutions
- Build the registry through the normal bootstrap API that snapshots the pre-dotenv environment
- Update codewhale so all crates are the same version and the registry always records host_environment
- If this reproduces with the standard bootstrap, file a bug - the invariant should always hold
Defensive patterns
Strategy: validation
Validate before calling
// Verify the invariant before merging plugin MCP servers:
if registry.host_environment().is_none() {
anyhow::bail!("registry built without pre-dotenv snapshot; rebuild it via the standard bootstrap");
}
merge_plugin_mcp_servers(&mut config, ®istry)?; Try / catch
match merge_plugin_mcp_servers(&mut config, ®istry) {
Err(e) if e.to_string().contains("pre-dotenv environment snapshot") => {
// rebuild the registry through the supported constructor and retry once
}
other => other,
} Prevention
- Always construct the plugin registry through the documented bootstrap path that captures host_environment
- Keep all codewhale crates at one version so registry construction and consumers agree
- In tests, use the real registry factory rather than hand-assembled structs
When it happens
Trigger: Calling merge_plugin_mcp_servers (directly or via manager bootstrap) with a registry constructed without capturing the pre-dotenv environment - e.g. a custom or test-built registry using a lower-level constructor, or version skew after an upgrade.
Common situations: Upgrading to a version where registry construction changed; embedding the registry in tests or external tools that bypass the standard bootstrap path.
Related errors
- MCP connection disappeared for {server_name}
- Failed to store MCP connection for {server_name}
- reviewed plugin MCP argument path escaped its staged root
- reviewed plugin MCP path escaped its staged root
- Reviewed plugin MCP authentication failed (provider details
AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16).
Data as JSON: /api/errors/42611e8450bed454.
Report an issue: GitHub.