zed-industries/zed · warning
aborting reconnect, because not in state that allows reconne
Error message
aborting reconnect, because not in state that allows reconnecting: {state} What it means
RemoteClient's reconnect flow only runs from states that still own a remote connection. State::can_reconnect() (crates/remote/src/remote_client.rs:228) is true only for Connected, HeartbeatMissed and ReconnectFailed; calling reconnect from Connecting, Reconnecting, ReconnectExhausted, ServerNotRunning - or with no state set at all - logs and bails with the offending state name (crates/remote/src/remote_client.rs:601).
Source
Thrown at crates/remote/src/remote_client.rs:601
drop(delegate);
})
}
fn reconnect(&mut self, cx: &mut Context<Self>) -> Result<()> {
let can_reconnect = self
.state
.as_ref()
.map(|state| state.can_reconnect())
.unwrap_or(false);
if !can_reconnect {
let state = if let Some(state) = self.state.as_ref() {
state.to_string()
} else {
"no state set".to_string()
};
log::info!(
"aborting reconnect, because not in state that allows reconnecting: {state}"
);
anyhow::bail!(
"aborting reconnect, because not in state that allows reconnecting: {state}"
);
}
let state = self.state.take().unwrap();
let (attempts, remote_connection, delegate) = match state {
State::Connected {
remote_connection,
delegate,
multiplex_task,
heartbeat_task,
}
| State::HeartbeatMissed {
remote_connection,
delegate,
multiplex_task,
heartbeat_task,View on GitHub (pinned to 5a9b9558db)
Solutions
- Let the client's own reconnection state machine drive reconnects instead of calling reconnect() manually from every error handler
- Before forcing a reconnect, wait until the client leaves Connecting/Reconnecting (check its connection-state API)
- After ReconnectExhausted or ServerNotRunning, start a brand-new connection instead of reconnecting the dead one
Defensive patterns
Strategy: validation
Validate before calling
// Only reconnect when the client can actually retry:
// allowed states are Connected, HeartbeatMissed, ReconnectFailed.
// Externally, gate on the client's connection-state API instead of calling reconnect() blindly.
if remote_client.connection_state() == ConnectionState::Disconnected {
remote_client.reconnect(cx);
} Try / catch
match remote_client.reconnect(cx) {
Err(e) if e.to_string().contains("not in state that allows reconnecting") => {
// benign guard: another reconnect is already in flight - ignore
}
other => other?,
} Prevention
- Centralize reconnect triggers in one place; never fan out reconnect() from every error handler
- After ReconnectExhausted or ServerNotRunning, create a new connection rather than reconnecting the old client
When it happens
Trigger: Invoking RemoteClient::reconnect while the client is Connecting or already Reconnecting (a double reconnect), after reconnect attempts were exhausted (ReconnectExhausted), after the server was detected as not running, or before any state was established.
Common situations: Multiple components reacting to the same disconnect and racing to reconnect; custom retry loops stacked on top of the client's built-in reconnection; reconnecting a client that was never shut down cleanly.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- build ids may only contain lowercase letters, numbers, '.',
- registry dataset requires a name
- cannot open repository on disconnected remote machine
- unknown uname: {uname:?}
- Prebuilt remote servers are not yet available for {os:?}. Se
AI-assisted analysis of zed-industries/zed@5a9b9558db (2026-08-20).
Data as JSON: /api/errors/642299390c828e92.
Report an issue: GitHub.