Hmbown/CodeWhale · error · anyhow::Error
Failed to store MCP connection for {server_name}
Error message
Failed to store MCP connection for {server_name} What it means
Immediately after connections.insert(server_name.to_string(), connection), get_or_connect calls connections.get_mut(server_name). Since insert with a freshly owned String key guarantees presence and &mut self prevents concurrent mutation, a None return contradicts the HashMap contract. Like the 'connection disappeared' branch above it is a defensive invariant check, not an expected runtime condition.
Source
Thrown at crates/tui/src/mcp.rs:2687
.ok_or_else(|| anyhow::anyhow!("Failed to find MCP server: {server_name}"))?;
if !server_config.is_enabled() {
anyhow::bail!("Failed to connect MCP server '{server_name}': server is disabled");
}
let mut connection = McpConnection::connect_with_policy(
server_name.to_string(),
server_config,
&self.config.timeouts,
self.network_policy.as_ref(),
)
.await?;
connection.catalog_generation = self.catalog_generation.load(Ordering::SeqCst);
self.connections.insert(server_name.to_string(), connection);
self.connections
.get_mut(server_name)
.ok_or_else(|| anyhow::anyhow!("Failed to store MCP connection for {server_name}"))
}
/// Connect to all enabled servers, returning errors for failed connections
pub async fn connect_all(&mut self) -> Vec<(String, anyhow::Error)> {
let mut errors = Vec::new();
// Reload before taking the configured-name snapshot. Previously the
// first call after adding a server captured the old names, then only
// noticed the config change inside `get_or_connect`, delaying the new
// server until a second turn.
if let Err(err) = self.reload_if_config_changed().await {
errors.push(("configuration".to_string(), err));
return errors;
}
let names: Vec<String> = self
.config
.servers
.keys()
.filter(|n| self.config.servers[*n].is_enabled())View on GitHub (pinned to 8880682c63)
Solutions
- Treat as an internal bug: capture logs and a reproduction and report it against the mcp module.
- Audit any local modifications to get_or_connect or the connections map type.
- Retry via get_or_connect once to see if it reproduces; persistent occurrence indicates corrupted state — restart the session.
Defensive patterns
Strategy: validation
Try / catch
// Rust: internal invariant — report and retry once
match pool.get_or_connect(name).await {
Err(e) if e.to_string().contains("Failed to store MCP connection") => {
tracing::error!("internal HashMap invariant broken: {e:#}");
pool.get_or_connect(name).await
}
o => o,
} Prevention
- Consider it a defect signal — capture a reproducer for the maintainers.
- Don't patch around it by inserting into pool internals from outside.
- Restart the session if it recurs; state is suspect.
When it happens
Trigger: Unreachable in correct code: insert immediately followed by get_mut on the same key under an exclusive borrow cannot yield None.
Common situations: Not hit in practice; its appearance would indicate memory corruption, a custom HashMap with broken behavior, or a refactor that moved the insert behind a fallible operation.
Related errors
- MCP connection disappeared for {server_name}
- stdout unavailable
- stderr unavailable
- active plugin registry is missing its pre-dotenv environment
- failed to parse git log output
AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16).
Data as JSON: /api/errors/d8b2d3c9b31a88b4.
Report an issue: GitHub.