{"record":{"id":"5c04efda4bfd018d","repo":"vectordotdev/vector","slug":"poll-ready-must-be-called-first","errorCode":null,"errorMessage":"poll_ready must be called first","messagePattern":"poll_ready must be called first","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"src/sinks/util/service/net/mod.rs","lineNumber":333,"sourceCode":"                        Ok(maybe_socket) => match maybe_socket {\n                            Some(socket) => NetworkServiceState::Connected(socket),\n                            None => NetworkServiceState::Disconnected,\n                        },\n                        Err(_) => return Poll::Ready(Err(NetError::ServiceSocketChannelClosed)),\n                    }\n                }\n            };\n        }\n        Poll::Ready(Ok(()))\n    }\n\n    fn call(&mut self, buf: Vec<u8>) -> Self::Future {\n        let (tx, rx) = oneshot::channel();\n\n        let mut socket = match std::mem::replace(&mut self.state, NetworkServiceState::Sending(rx))\n        {\n            NetworkServiceState::Connected(socket) => socket,\n            _ => panic!(\"poll_ready must be called first\"),\n        };\n\n        Box::pin(async move {\n            match socket.send(&buf).await.context(net_error::FailedToSend) {\n                Ok(sent) => {\n                    // Emit an error if we weren't able to send the entire buffer.\n                    if sent != buf.len() {\n                        socket.on_partial_send(buf.len(), sent);\n                    }\n\n                    // Send the socket back to the service, since theoretically it's still valid to\n                    // reuse given that we may have simply overrun the OS socket buffers, etc.\n                    tx.send(Some(socket)).ok();\n\n                    Ok(sent)\n                }\n                Err(e) => {\n                    // We need to signal back to the service that it needs to create a fresh socket","sourceCodeStart":315,"sourceCodeEnd":351,"githubUrl":"https://github.com/vectordotdev/vector/blob/bdb87aeaa4c4ff27c0ba643c1c77b21bf2ef4013/src/sinks/util/service/net/mod.rs#L315-L351","documentation":"NetService::call panics when invoked while the internal state is not NetworkServiceState::Connected. The service swaps state to Sending on call, so like any Tower service it must have poll_ready() return Ready (restoring Connected) before call(). Hitting this means the ready/call protocol was violated. It is an internal invariant violation of the framed-network service state machine.","triggerScenarios":"Calling the service without a prior successful poll_ready(); calling call() twice without re-polling poll_ready(); wrapping the service in middleware that ignores readiness.","commonSituations":"Custom sink drivers or Tower layers composed around Vector's net service during development; regressions after refactoring batch/send drivers that bypass the readiness handshake.","solutions":["Ensure poll_ready() is awaited until Ready(Ok(())) immediately before each call()","Do not reuse the service for a second request before re-polling poll_ready()","Use tower::buffer::Buffer or Vector's existing service builders so the protocol is enforced for you"],"exampleFix":"// before\nnet_service.call(buf).await;\n\n// after\nready!(net_service.poll_ready(cx))?;\nnet_service.call(buf);","handlingStrategy":"type-guard","validationCode":"// Check readiness before sending\nready!(service.poll_ready(cx))?; // must yield Ready(Ok(())) before call","typeGuard":"fn is_connected(state: &NetworkServiceState) -> bool { matches!(state, NetworkServiceState::Connected(_)) }","tryCatchPattern":null,"preventionTips":["Follow the Tower contract: poll_ready → call, one request at a time","Never call twice without an intervening ready poll","Compose through tower::buffer::Buffer for automatic readiness management"],"tags":["rust","tower","network","async","panic"],"backgroundTag":"internal-invariant-violation","analyzedSha":"bdb87aeaa4c4ff27c0ba643c1c77b21bf2ef4013","analyzedAt":"2026-09-16T02:53:35.741Z","contentChangedAt":"2026-09-16T02:53:35.741Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}