diem/diem · error · NoiseHandshakeError
noise client: error sending client handshake init message: {
Error message
noise client: error sending client handshake init message: {0} What it means
NoiseHandshakeError::ClientWriteFailed wraps an io::Error that occurred while the Noise client was sending its initial handshake message over the socket. It means the write itself failed — the connection could not carry the handshake bytes — rather than a crypto or rejection issue.
Source
Thrown at network/src/noise/error.rs:19
// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0
use diem_crypto::noise::NoiseError;
use diem_types::PeerId;
use short_hex_str::ShortHexStr;
use std::io;
use thiserror::Error;
/// Different errors than can be raised when negotiating a Noise handshake.
#[derive(Debug, Error)]
pub enum NoiseHandshakeError {
#[error("noise client: MUST_FIX: missing remote server's public key when dialing")]
MissingServerPublicKey,
#[error("noise client: MUST_FIX: error building handshake init message: {0}")]
BuildClientHandshakeMessageFailed(NoiseError),
#[error("noise client: error sending client handshake init message: {0}")]
ClientWriteFailed(io::Error),
#[error(
"noise client: error reading server handshake response message, server \
probably rejected our handshake message: {0}"
)]
ClientReadFailed(io::Error),
#[error("noise client: error flushing socket after writing: {0}")]
ClientFlushFailed(io::Error),
#[error("noise client: error finalizing secure connection: {0}")]
ClientFinalizeFailed(NoiseError),
#[error("noise server: error reading client handshake init message: {0}")]
ServerReadFailed(io::Error),
#[error("noise server: client peer id is malformed: {0}")]View on GitHub (pinned to fc4714a8ea)
Solutions
- Check the server is running and reachable at the dialed address.
- Retry the dial with backoff — transient network failures commonly surface here.
- Inspect the wrapped io::Error for ECONNRESET/EPIPE and verify firewall/NAT rules between client and server.
- Verify the server's connection limits (max inbound peers) are not causing immediate disconnects.
Defensive patterns
Strategy: retry
Validate before calling
async fn can_reach(addr: SocketAddr) -> bool {
tokio::net::TcpStream::connect(addr).await.is_ok()
} Try / catch
match dial().await {
Err(NoiseHandshakeError::ClientWriteFailed(e)) if is_transient(&e) => {
backoff::retry(dial, MAX_ATTEMPTS).await
}
Err(e @ NoiseHandshakeError::ClientWriteFailed(_)) => { error!("fatal write failure: {}", e); Err(e) }
ok => ok.map(|_| ())?,
}
fn is_transient(e: &io::Error) -> bool {
matches!(e.kind(), io::ErrorKind::ConnectionReset | io::ErrorKind::ConnectionAborted | io::ErrorKind::TimedOut)
} Prevention
- Health-check the server before/while dialing.
- Use bounded retries with exponential backoff for transient io errors.
- Monitor connection limits and firewall rules between endpoints.
When it happens
Trigger: Calling write/send on the TCP (or other transport) stream during the first phase of the Noise client handshake when the socket is closed, reset, or otherwise unreadable by the OS.
Common situations: Server not listening or crashed mid-handshake; connection reset by peer/firewall; TLS or proxy layer terminated; network partition right after connect.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- noise client: MUST_FIX: missing remote server's public key w
- noise client: error reading server handshake response messag
- noise client: error flushing socket after writing: {0}
- noise server: error reading client handshake init message: {
- Failed reading validator_network_address_keys from storage
AI-assisted analysis of diem/diem@fc4714a8ea (2026-09-04).
Data as JSON: /api/errors/25e0abd68715fc81.
Report an issue: GitHub.