vectordotdev/vector · error · std::io::Error

NotConnected

NotConnected

Error message

Can't set keepalive on connection that has not been accepted yet.

What it means

Runtime `io::Error` (kind `NotConnected`) from `MaybeTlsIncomingStream::set_keepalive` in lib/vector-core/src/tls/incoming.rs. The stream wraps a state machine: with TLS enabled the connection starts in `StreamState::Accepting` (handshake future in flight) and `get_ref()` only returns the `TcpStream` once the handshake completes and state becomes `Accepted`. Calling `set_keepalive` before that yields this error.

Source

Thrown at lib/vector-core/src/tls/incoming.rs:294

            ),
            None => StreamState::Accepted(MaybeTlsStream::Raw(stream)),
        };
        Self { state, peer_addr }
    }

    // Explicit handshake method
    pub async fn handshake(&mut self) -> crate::tls::Result<()> {
        if let StreamState::Accepting(fut) = &mut self.state {
            let stream = fut.await?;
            self.state = StreamState::Accepted(MaybeTlsStream::Tls(stream));
        }

        Ok(())
    }

    pub fn set_keepalive(&mut self, keepalive: TcpKeepaliveConfig) -> io::Result<()> {
        let stream = self.get_ref().ok_or_else(|| {
            io::Error::new(
                io::ErrorKind::NotConnected,
                "Can't set keepalive on connection that has not been accepted yet.",
            )
        })?;

        if let Some(time_secs) = keepalive.time_secs {
            let config =
                socket2::TcpKeepalive::new().with_time(std::time::Duration::from_secs(time_secs));

            tcp::set_keepalive(stream, &config)?;
        }

        Ok(())
    }

    pub fn set_receive_buffer_bytes(&mut self, bytes: usize) -> std::io::Result<()> {
        let stream = self.get_ref().ok_or_else(|| {
            io::Error::new(

View on GitHub (pinned to 3708c39b12)

Solutions

  1. Await the handshake first: `stream.handshake().await?;` then `stream.set_keepalive(cfg)?`
  2. Or defer setting keepalive until after the first successful read/write (which also completes the handshake)
  3. Treat `ErrorKind::NotConnected` from this call as 'not yet accepted' — retry after the handshake rather than failing the connection

Example fix

// before
let mut stream = listener.accept().await?;
stream.set_keepalive(keepalive)?; // fails under TLS

// after
let mut stream = listener.accept().await?;
stream.handshake().await?;
stream.set_keepalive(keepalive)?;
Defensive patterns

Strategy: validation

Validate before calling

// Only tune socket options once the TLS handshake is done
stream.handshake().await?; // completes Accepting -> Accepted
if stream.get_ref().is_some() {
    stream.set_keepalive(keepalive)?;
}

Try / catch

match stream.set_keepalive(cfg) {
    Err(e) if e.kind() == std::io::ErrorKind::NotConnected => {
        // handshake still pending: drive I/O or await handshake(), then retry once
    }
    Err(e) => return Err(e.into()),
    Ok(()) => {}
}

Prevention

When it happens

Trigger: In a TCP source with TLS enabled, calling `stream.set_keepalive(...)` immediately after accept, before `stream.handshake().await` has completed (or before any read/write drove the handshake to completion). With plain TCP (no acceptor) the state is `Accepted` from construction, so the same code appears to work until TLS is configured.

Common situations: Sources that configure `keepalive_time_secs` per connection (e.g. socket sources adding keepalive in their connection setup) and only fail in TLS deployments; also hitting the `Closed` state after the connection was torn down.

Related errors


AI-assisted analysis of vectordotdev/vector@3708c39b12 (2026-08-20). Data as JSON: /api/errors/3344fdcfcaa53fc1. Report an issue: GitHub.