The unrecognized-message-type branch tries to fall back to "UNREADABLE"
by doing raise UnicodeDecodeError with no arguments. That doesn't work
UnicodeDecodeError needs 5 constructor arguments, so this actually raises
a TypeError, which the surrounding except UnicodeDecodeError doesn't
catch. The script crashes instead of labeling the message and continuing.
Since output is only written after the whole capture file is processed, one bad message type loses the entire parse.
This isn't just theoretical: v2 transport accepts message-type byte 0x7F (net.cpp, V2Transport::GetMessageType), which v1 rejects (protocol.cpp, IsMessageTypeValid). 0x7F is valid UTF-8 but not printable, so a peer sending an unrecognized v2 message type containing it produces a capture record that crashes the parser on the next parse.
Repro:
$ python3 -c "
import struct
msgtype = b'\x01bad' + b'\x00'*8
open('msgs_recv.dat','wb').write(struct.pack('<q', 1234567890) + msgtype + struct.pack('<i', 0))"
$ python3 contrib/message-capture/message-capture-parser.py msgs_recv.dat
TypeError: function takes exactly 5 arguments (0 given)
With this fix it correctly outputs "msgtype": "UNREADABLE" and exits 0.
Note there's no automated test covering message-capture-parser.py's output (p2p_message_capture.py has its own separate structural parser and says this script "should be verified manually") likely why this went unnoticed. Verified manually with the repro above and confirmed the existing invalid-UTF-8 fallback path is unaffected.