vectordotdev/vector · error

Can't set keepalive on connection that has not been…

Error message

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

What it means

`IncomingTlsListener::set_keepalive` needs a reference to the accepted TCP stream. The wrapper holds `Option<T>` and returns `Err(NotConnected)` when called before a connection has been accepted and stored, since there is no socket on which to apply the keepalive options.

Solutions

  1. Apply keepalive only after the connection has been accepted (call it inside handle_stream / after awaiting accept).
  2. Check that the wrapper was created from an accepted stream, not a fresh listener.
  3. Set keepalive via TcpKeepaliveConfig so it is applied post-accept automatically.

Example fix

// before
let mut conn = listener.accept().await?; // not yet polled to completion
conn.set_keepalive(cfg)?;

// after
let mut conn = listener.accept().await?.into_stream();
conn.set_keepalive(cfg).await?; // after connection exists
Defensive patterns

Strategy: try-catch

Validate before calling

if conn.get_ref().is_none() {
    return Err(std::io::Error::new(std::io::ErrorKind::NotConnected, "connection not accepted yet"));
}

Type guard

// Rust: match on the Option inside the wrapper
fn is_accepted(conn: &IncomingConnection) -> bool { conn.get_ref().is_some() }

Try / catch

match conn.set_keepalive(cfg) {
    Err(e) if e.kind() == std::io::ErrorKind::NotConnected => {
        // defer or skip; connection not yet accepted
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling `set_keepalive` on the listener's connection wrapper before the accept future completes / before `handle_stream` has stored the accepted stream.

Common situations: Configuring TCP keepalive from a different task than the one that awaits the accept, or racing accept and socket tuning; usually surfaces as NotConnected on a TLS listener wrapper.

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


AI-assisted analysis of vectordotdev/vector@bdb87aeaa4 (2026-09-16). Data as JSON: /api/errors/25707aea3cf4b50b. Report an issue: GitHub.

Appendix: source

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

            ),
            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 bdb87aeaa4)