locustio/locust · error · RPCError
ZMQ network broken
Error message
ZMQ network broken
What it means
RPCError raised when the ZMQ socket itself fails during recv() (as opposed to message corruption). It wraps zmq.error.ZMQError — most commonly ZMQ's 'context was terminated' or 'socket closed' — indicating the transport is no longer usable, so the library surfaces it as a fatal network error rather than a receive error.
Source
Thrown at locust/rpc/zmqrpc.py:45
self.socket.send(msg.serialize(), zmq.NOBLOCK)
except zmqerr.ZMQError as e:
raise RPCSendError("ZMQ sent failure") from e
@retry()
def send_to_client(self, msg):
try:
self.socket.send_multipart([msg.node_id.encode(), msg.serialize()])
except zmqerr.ZMQError as e:
raise RPCSendError("ZMQ sent failure") from e
def recv(self):
try:
data = self.socket.recv()
msg = Message.unserialize(data)
except msgerr.ExtraData as e:
raise RPCReceiveError("ZMQ interrupted message") from e
except zmqerr.ZMQError as e:
raise RPCError("ZMQ network broken") from e
return msg
def recv_from_client(self):
try:
data = self.socket.recv_multipart()
addr = data[0].decode()
except UnicodeDecodeError as e:
raise RPCReceiveError("ZMQ interrupted or corrupted message") from e
except zmqerr.ZMQError as e:
raise RPCError("ZMQ network broken") from e
try:
msg = Message.unserialize(data[1])
except (UnicodeDecodeError, msgerr.ExtraData) as e:
raise RPCReceiveError("ZMQ interrupted or corrupted message", addr=addr) from e
return addr, msg
def close(self, linger=None):
self.socket.close(linger=linger)View on GitHub (pinned to f391a716e1)
Solutions
- Ensure listener/recv greenlets are stopped before closing the ZMQ context or quitting the runner
- Catch RPCError around recv loops during shutdown and exit the loop cleanly
- Avoid sharing ZMQ sockets across greenlets that outlive the Environment
- If it happens mid-run, restart the runner process — the context is unrecoverable
Example fix
// before
def worker(client, environment):
while True:
msg = client.recv() # raises RPCError at shutdown
// after
def worker(client, environment):
while True:
try:
msg = client.recv()
except RPCError:
break # context/socket closed, stop listener Defensive patterns
Strategy: try-catch
Try / catch
try:
msg = client.recv()
except RPCError:
break # context/socket closed; exit the receive loop cleanly Prevention
- Stop all recv greenlets before quitting the Environment
- Never close/destroy ZMQ sockets or context while listeners run
- Wrap long-lived recv loops in try/except RPCError for clean shutdown
When it happens
Trigger: Calling recv() (directly or via wait_for_reply/worker loops) after the ZMQ context was terminated or the socket was closed — e.g. during Environment quit/teardown while a listener greenlet is still blocked in recv.
Common situations: Test teardown racing with listener greenlets; process shutdown while recv is blocked; destroying the zmq context while another greenlet still uses the socket.
Related errors
- ZMQ sent failure
- ZMQ interrupted message
- ZMQ interrupted or corrupted message
- Socket bind failure: {e}
- You need to install pymongo or at least bson to be able to s
AI-assisted analysis of locustio/locust@f391a716e1 (2026-08-29).
Data as JSON: /api/errors/323353670f65a676.
Report an issue: GitHub.