HelloZeroNet/ZeroNet · error · AnnounceError
Invalid response: %r
Error message
Invalid response: %r
What it means
After the UDP announce, poll_once() returned something, but it is neither None/empty nor a dict containing a "response" key. The plugin raises AnnounceError("Invalid response: %r") with the raw payload. This guards the shape of the decoded bencode UDP reply before reading back["response"]["peers"].
Source
Thrown at plugins/AnnounceBitTorrent/AnnounceBitTorrentPlugin.py:69
raise AnnounceError("Udp trackers not available with proxies")
ip, port = tracker_address.split("/")[0].split(":")
tracker = UdpTrackerClient(ip, int(port))
if helper.getIpType(ip) in self.getOpenedServiceTypes():
tracker.peer_port = self.fileserver_port
else:
tracker.peer_port = 0
tracker.connect()
if not tracker.poll_once():
raise AnnounceError("Could not connect")
tracker.announce(info_hash=self.site.address_sha1, num_want=num_want, left=431102370)
back = tracker.poll_once()
if not back:
raise AnnounceError("No response after %.0fs" % (time.time() - s))
elif type(back) is dict and "response" in back:
peers = back["response"]["peers"]
else:
raise AnnounceError("Invalid response: %r" % back)
return peers
def httpRequest(self, url):
headers = {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.3',
'Accept-Encoding': 'none',
'Accept-Language': 'en-US,en;q=0.8',
'Connection': 'keep-alive'
}
req = urllib.request.Request(url, headers=headers)
if config.trackers_proxy == "tor":
tor_manager = self.site.connection_server.tor_manager
handler = sockshandler.SocksiPyHandler(socks.SOCKS5, tor_manager.proxy_ip, tor_manager.proxy_port)View on GitHub (pinned to 454c0b2e7e)
Solutions
- Inspect the %r value in the message — if it contains an 'error' key, the tracker rejected the announce; read its reason.
- Verify the site's address_sha1/info_hash is valid and the tracker supports it.
- Use alternative trackers; drop trackers that consistently return invalid responses.
- Ensure the UDP socket is only receiving from the tracker (port conflicts).
Example fix
// before
else:
raise AnnounceError("Invalid response: %r" % back)
// after
elif type(back) is dict and "error" in back:
self.site.log.warning("Tracker error: %r" % back)
return []
else:
raise AnnounceError("Invalid response: %r" % back) Defensive patterns
Strategy: type-guard
Type guard
def is_valid_announce_response(back):
return isinstance(back, dict) and "response" in back and isinstance(back["response"], dict) Try / catch
try:
peers = announce_plugin.announceTrackerUdp(tracker_address, file_info)
except AnnounceError as e:
log.warning("Invalid tracker reply: %s" % e)
peers = [] Prevention
- Bind the UDP socket to a dedicated port to avoid stray datagrams
- Log raw responses (the %r payload) to identify trackers sending error packets
- Drop trackers that repeatedly return non-standard replies
- Keep client protocol/format aligned with tracker expectations
When it happens
Trigger: Tracker replies with an error packet (e.g. b'error': b'...'), a malformed/non-bencode datagram, or an intermediate device (captive portal, DPI box) sends junk UDP data that gets decoded into an unexpected object.
Common situations: Trackers rejecting announces with error messages (wrong info_hash, banned client); responses from a different socket/peer landing on the same port; corrupted datagrams on lossy networks.
Related errors
- Could not connect
- No response after %.0fs
- Invalid response: %s
- Invalid response: %r (%s)
- Udp disabled by config
AI-assisted analysis of HelloZeroNet/ZeroNet@454c0b2e7e (2026-09-02).
Data as JSON: /api/errors/e43049abff4555de.
Report an issue: GitHub.