@@ -647,22 +647,36 @@ async def handle_incoming(self) -> None:
647647 try :
648648 header = await read_exactly (self .secured_conn , HEADER_SIZE )
649649 except IncompleteReadError as e :
650- # Get transport context for better debugging
651- transport_type = "unknown"
652- try :
653- if hasattr (self .secured_conn , "conn_state" ):
654- conn_state_method = getattr (self .secured_conn , "conn_state" )
655- if callable (conn_state_method ):
656- state = conn_state_method ()
657- if isinstance (state , dict ):
658- transport_type = state .get ("transport" , "unknown" )
659- except Exception :
660- pass
661-
662- logger .error (
663- f"Yamux connection closed during header read for peer "
664- f"{ self .peer_id } : { e } . Transport: { transport_type } ."
665- )
650+ # Check if this is a clean connection closure (0 bytes received)
651+ # This happens when the peer closes the connection gracefully
652+ # after completing their operations (e.g., after ping/pong)
653+ if e .is_clean_close :
654+ # Clean connection closure - this is normal when peer
655+ # disconnects after completing protocol exchange
656+ logger .info (
657+ f"Yamux connection closed cleanly by peer { self .peer_id } "
658+ )
659+ else :
660+ # Unexpected partial read - log as warning
661+ transport_type = "unknown"
662+ try :
663+ if hasattr (self .secured_conn , "conn_state" ):
664+ conn_state_method = getattr (
665+ self .secured_conn , "conn_state"
666+ )
667+ if callable (conn_state_method ):
668+ state = conn_state_method ()
669+ if isinstance (state , dict ):
670+ transport_type = state .get (
671+ "transport" , "unknown"
672+ )
673+ except Exception :
674+ pass
675+ logger .warning (
676+ f"Yamux connection closed unexpectedly for peer "
677+ f"{ self .peer_id } : { e } . Transport: { transport_type } ."
678+ )
679+
666680 self .event_shutting_down .set ()
667681 await self ._cleanup_on_error ()
668682 break
@@ -927,26 +941,20 @@ async def handle_incoming(self) -> None:
927941 self .stream_events [stream_id ].set ()
928942 except Exception as e :
929943 # Special handling for expected IncompleteReadError on stream close
930- # This occurs when the connection closes while reading the header
931- # (12 bytes)
944+ # This occurs when the connection closes while reading
932945 if isinstance (e , IncompleteReadError ):
933- details = getattr (e , "args" , [{}])[0 ]
934- if (
935- isinstance (details , dict )
936- and details .get ("requested_count" ) == HEADER_SIZE
937- and details .get ("received_count" ) == 0
938- ):
946+ if e .is_clean_close :
939947 logger .info (
940- f"Stream closed cleanly for peer { self .peer_id } "
941- + f" (IncompleteReadError: { details } )"
948+ f"Yamux connection closed cleanly for peer { self .peer_id } "
942949 )
943950 self .event_shutting_down .set ()
944951 await self ._cleanup_on_error ()
945952 break
946953 else :
947- logger .error (
948- f"Error in handle_incoming for peer { self .peer_id } : "
949- + f"{ type (e ).__name__ } : { str (e )} "
954+ # Partial read - log as warning, not error
955+ logger .warning (
956+ f"Incomplete read in handle_incoming for peer "
957+ f"{ self .peer_id } : { e } "
950958 )
951959 else :
952960 # Handle RawConnError with more nuance
0 commit comments