Skip to content

Commit fcb9c28

Browse files
committed
fix(worker): graceful skip when Servers or Messages data is absent
A user reported UNKNOWN_ERROR for package 4aa23a2a6ea2f52ba9016a723143b792. Traceback: File "/app/tasks.py", line 466, in read_analytics_file server_content = zip.open(server_path) KeyError: "There is no item named 'Servers/index.json' in the archive" Same fallback bug that PR #82 fixed for the analytics path: when the discovered root is None, the old code blindly assigned the canonical literal 'Servers/index.json' (resp. 'Messages/index.json') and let zip.open KeyError if that file isn't actually in the archive. That happens when the user un-ticks 'Servers' (or 'Messages') in Discord's data-request form. Fix: only assign a path that actually exists in zip.namelist(); if nothing matches, set it to None and skip the read block, marking is_partial=True. The rest of the worker copes with empty servers / empty channels lists (the message-CSV walker filters by namelist anyway, so it just processes 0 channels). After this: - No Servers folder → no guild-scoped stats but DMs/friends/payments OK - No Messages folder → no channel-scoped stats but server list/payments OK - Both missing → minimal package, but no crash
1 parent f3ff71d commit fcb9c28

1 file changed

Lines changed: 42 additions & 19 deletions

File tree

src/tasks.py

Lines changed: 42 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -456,36 +456,59 @@ def read_analytics_file(package_status_id, package_id, link, session):
456456

457457
namelist = zip.namelist()
458458
servers_root = find_servers_root(namelist)
459-
if not servers_root:
459+
# Resolve server_path defensively: only assign a path that actually
460+
# exists in the zip. Don't fall through to the canonical literal
461+
# 'Servers/index.json' and let zip.open KeyError — that's the
462+
# UNKNOWN_ERROR users hit when they un-tick "Servers" in Discord's
463+
# data-request form.
464+
if servers_root:
465+
server_path = f'{servers_root}/index.json'
466+
elif 'Servers/index.json' in namelist:
460467
server_path = 'Servers/index.json'
461-
if server_path not in namelist and 'servers/index.json' in namelist:
462-
server_path = 'servers/index.json'
468+
elif 'servers/index.json' in namelist:
469+
server_path = 'servers/index.json'
463470
else:
464-
server_path = f'{servers_root}/index.json'
465-
466-
server_content = zip.open(server_path)
467-
server_json = orjson.loads(server_content.read())
468-
for guild_id in server_json:
469-
guilds.append({
470-
'id': guild_id,
471-
'name': server_json[guild_id]
472-
})
471+
server_path = None
472+
473+
if server_path:
474+
server_content = zip.open(server_path)
475+
server_json = orjson.loads(server_content.read())
476+
for guild_id in server_json:
477+
guilds.append({
478+
'id': guild_id,
479+
'name': server_json[guild_id]
480+
})
481+
else:
482+
# Server data missing — DMs, friends, payments, profile still
483+
# process. Mark partial so the frontend can render server-scoped
484+
# stats as N/A (issue dumpus-app/dumpus-app#232 covers the banner).
485+
print('No Servers/index.json found — skipping server data; package is partial.')
486+
is_partial = True
473487

474488
'''
475489
Read Channels Data.
476490
This will be used later to get the channel name from the channel_id (or to check whether it is a DM or a Guild Channel).
477491
'''
478492

479493
messages_root = find_messages_root(namelist)
480-
if not messages_root:
494+
# Same defensive resolution as servers above.
495+
if messages_root:
496+
message_index_path = f'{messages_root}/index.json'
497+
elif 'Messages/index.json' in namelist:
481498
message_index_path = 'Messages/index.json'
482-
if message_index_path not in namelist and 'messages/index.json' in namelist:
483-
message_index_path = 'messages/index.json'
499+
elif 'messages/index.json' in namelist:
500+
message_index_path = 'messages/index.json'
484501
else:
485-
message_index_path = f'{messages_root}/index.json'
486-
487-
message_index_content = zip.open(message_index_path)
488-
message_index_json = orjson.loads(message_index_content.read())
502+
message_index_path = None
503+
504+
if message_index_path:
505+
message_index_content = zip.open(message_index_path)
506+
message_index_json = orjson.loads(message_index_content.read())
507+
else:
508+
print('No Messages/index.json found — skipping channel data; package is partial.')
509+
is_partial = True
510+
message_index_json = {}
511+
489512
for channel_id in message_index_json:
490513
full_name = message_index_json[channel_id]
491514
if full_name is None:

0 commit comments

Comments
 (0)