HelloZeroNet/ZeroNet · error · AnnounceError
Invalid response: %r (%s)
Error message
Invalid response: %r (%s)
What it means
The HTTP tracker replied, the body was bencode-decoded and b"peers" extracted, but parsing the 6-byte-per-peer compact format (unpack '!LH' / inet_ntoa) threw an exception. The plugin wraps it in AnnounceError("Invalid response: %r (%s)") including the raw response and the formatted exception.
Source
Thrown at plugins/AnnounceBitTorrent/AnnounceBitTorrentPlugin.py:146
req.close()
req = None
if not response:
raise AnnounceError("No response after %.0fs" % (time.time() - s))
# Decode peers
try:
peer_data = bencode_open.loads(response)[b"peers"]
response = None
peer_count = int(len(peer_data) / 6)
peers = []
for peer_offset in range(peer_count):
off = 6 * peer_offset
peer = peer_data[off:off + 6]
addr, port = struct.unpack('!LH', peer)
peers.append({"addr": socket.inet_ntoa(struct.pack('!L', addr)), "port": port})
except Exception as err:
raise AnnounceError("Invalid response: %r (%s)" % (response, Debug.formatException(err)))
return peers
View on GitHub (pinned to 454c0b2e7e)
Solutions
- Read the exception detail and raw response in the message — a 'failure reason' payload means the tracker rejected the announce.
- Ensure the announce URL requests compact responses (peer batching) as this parser only handles 6-byte compact peers.
- Check whether tracker returned dict-style peers and add handling for that format.
- Switch to a working tracker in the site's tracker list.
- Verify no proxy is rewriting the response body.
Example fix
// before
peer_data = bencode_open.loads(response)[b"peers"]
// after
parsed = bencode_open.loads(response)
if not isinstance(parsed.get(b"peers"), (bytes, bytearray)):
raise AnnounceError("Tracker failure: %r" % parsed)
peer_data = parsed[b"peers"] Defensive patterns
Strategy: validation
Validate before calling
parsed = bencode_open.loads(response)
peer_data = parsed.get(b"peers")
if isinstance(peer_data, dict):
raise ValueError("Tracker returned non-compact peers dict")
if not isinstance(peer_data, (bytes, bytearray)) or len(peer_data) % 6 != 0:
raise ValueError("Peers payload not 6-byte aligned compact format") Type guard
def is_compact_peer_list(peer_data):
return isinstance(peer_data, (bytes, bytearray)) and len(peer_data) % 6 == 0 Try / catch
try:
peers = announce_plugin.announceTrackerHttp(tracker_address, file_info)
except AnnounceError as e:
log.warning("Unparseable tracker response: %s" % e)
peers = [] Prevention
- Always request compact peer responses in the announce URL
- Check for b'failure reason' in bencode replies before parsing peers
- Verify response body is pure bencode (no proxy-injected HTML)
- Handle dict-style (non-compact) peer responses as a fallback
When it happens
Trigger: peer_data length is not a multiple of 6 (truncated body, HTML error page that happened to bencode-decode, dict-style peers response instead of compact string), or peer_data is a dict/list not bytes so len()/slicing misbehaves.
Common situations: Trackers returning non-compact peer lists (dict with peer id fields) when compact=1 isn't honored; trackers returning error bencode like {b'failure reason': ...} with no b'peers'; proxy-injected HTML corrupting the body.
Related errors
- Invalid response: %r
- Invalid response: %s
- Could not connect
- No response after %.0fs
- No multipart header found
AI-assisted analysis of HelloZeroNet/ZeroNet@454c0b2e7e (2026-09-02).
Data as JSON: /api/errors/6f925f24086715ce.
Report an issue: GitHub.