From 48e0a89125793af820579f3ca57e89be5b796968 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Tue, 25 Nov 2025 15:11:35 +1100 Subject: [PATCH] fix(connlib): fail connection upsert early (#10962) When upserting a connection, we need to sample one of our relays to use as a fallback. If we don't have any relays (because they all got disconnected), we cannot create the connection. Right now, we perform this sampling a bit too late in the function and thus wrongly print "Creating new connection" even though we never make it that for. To avoid that, move the `sample_relay` call higher up to avoid making any state modifications if we cannot proceed. --- rust/connlib/snownet/src/node.rs | 4 ++-- rust/connlib/tunnel/src/tests/sut.rs | 10 ++++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/rust/connlib/snownet/src/node.rs b/rust/connlib/snownet/src/node.rs index 22f6f1da9..ad0e95dc7 100644 --- a/rust/connlib/snownet/src/node.rs +++ b/rust/connlib/snownet/src/node.rs @@ -305,6 +305,8 @@ where return Ok(()); } + let selected_relay = self.sample_relay()?; + let existing = self.connections.remove_established(&cid, now); let index = self.index.next(); @@ -315,8 +317,6 @@ where tracing::info!(local = ?local_creds, remote = ?remote_creds, %index, "Creating new connection"); } - let selected_relay = self.sample_relay()?; - let mut agent = match self.role.kind() { RoleKind::Client => new_client_agent(), RoleKind::Server => new_server_agent(), diff --git a/rust/connlib/tunnel/src/tests/sut.rs b/rust/connlib/tunnel/src/tests/sut.rs index 975ad4516..f8cebc2da 100644 --- a/rust/connlib/tunnel/src/tests/sut.rs +++ b/rust/connlib/tunnel/src/tests/sut.rs @@ -535,12 +535,18 @@ impl TunnelTest { if let Some(event) = self.client.exec_mut(|c| c.sut.poll_event()) { match self.on_client_event(self.client.inner().id, event, &ref_state.portal) { Ok(()) => {} - Err(AuthorizeFlowError::Client(_)) => { + Err(AuthorizeFlowError::Client(e)) => { + tracing::debug!("Failed to handle ClientEvent: {e}"); + + // Simulate WebSocket reconnect ... self.client.exec_mut(|c| { c.update_relays(iter::empty(), self.relays.iter(), now); }); } - Err(AuthorizeFlowError::Gateway(_)) => { + Err(AuthorizeFlowError::Gateway(e)) => { + tracing::debug!("Failed to handle GatewayEvent: {e}"); + + // Simulate WebSocket reconnect ... for gateway in self.gateways.values_mut() { gateway.exec_mut(|g| { g.update_relays(iter::empty(), self.relays.iter(), now)