diem/diem · error · NoiseHandshakeError
noise client: error finalizing secure connection: {0}
Error message
noise client: error finalizing secure connection: {0} What it means
NoiseHandshakeError::ClientFinalizeFailed wraps a diem_crypto NoiseError raised when the client cannot finalize the secure connection after receiving the server's response — i.e. the second Noise handshake step fails cryptographically. This usually means the peer is not who the client expected (wrong static key) or the response bytes are corrupt/malicious.
Source
Thrown at network/src/noise/error.rs:31
#[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}")]
InvalidClientPeerId(String),
#[error("noise server: detected self-dial: we're trying to connect to ourselves")]
SelfDialDetected,
#[error(
"noise server: client {0}: client is expecting us to have a different \
public key: {1}"
)]
ClientExpectingDifferentPubkey(ShortHexStr, String),
#[error("noise server: client {0}: error parsing handshake init message: {1}")]View on GitHub (pinned to fc4714a8ea)
Solutions
- Verify the client's configured server public key matches the server's current static key.
- Ensure both sides use the identical Noise protocol name/handshake pattern and cipher suite.
- Capture and log the wrapped NoiseError ({0}) to identify MAC vs malformed-message failure.
- If keys rotated, update client config and redial; treat repeated failures as a possible security event.
Example fix
// before trusted_pubkey = old_server_key; // rotated // after trusted_pubkey = fetch_current_server_key(peer_id); // update after rotation
Defensive patterns
Strategy: try-catch
Validate before calling
fn validate_pinned_key(expected: &X25519PublicKey, current: &X25519PublicKey) -> bool {
expected == current
} Try / catch
match handshake().await {
Err(NoiseHandshakeError::ClientFinalizeFailed(e)) => {
error!("could not authenticate server: {} — possible key rotation or MITM; do not retry blindly", e);
alert_security_and_refresh_pinned_key();
}
ok => ok.map(|_| ())?,
} Prevention
- Keep the pinned server public key in sync after any server key rotation.
- Pin the exact Noise protocol name/pattern on both sides.
- Alert on repeated finalize failures — repeated MAC failures can indicate interception.
- Verify key material integrity (hex decode, 32-byte length) at load time.
When it happens
Trigger: Calling the final handshake state transition (e.g. read_message/into_transport) on the client after the server's response arrives, when MAC verification fails, the remote static key doesn't match the expected server pubkey, or the message is malformed.
Common situations: Server rotated keys but client config still has the old pubkey; MITM or corrupted traffic; mismatched noise protocol name/pattern between endpoints; bug supplying wrong handshake state.
Related errors
- noise client: MUST_FIX: error building handshake init messag
- noise server: client {0}: client is expecting us to have a d
- noise client: MUST_FIX: missing remote server's public key w
- noise client: error sending client handshake init message: {
- noise client: error reading server handshake response messag
AI-assisted analysis of diem/diem@fc4714a8ea (2026-09-04).
Data as JSON: /api/errors/06b4c12e3780fab6.
Report an issue: GitHub.