Skip to content

Commit b795af0

Browse files
committed
feat(worker): MISSING_USER_DATA error when user.json is absent
Discord exports drop user.json (and the entire Account folder) when the user un-ticks the 'User data' checkbox in the request form. We need user.json to anchor the rest of the analysis on the package owner's identity, so a package without it has nothing useful to compute. The old code path landed on a KeyError("There is no item named 'Account/user.json' in the archive") and got relabeled UNKNOWN_ERROR in process_package — multiple users in production hit this and retried 4+ times before giving up. Now: when neither find_user_root() nor either legacy fallback locates a user.json entry, raise MISSING_USER_DATA. The error code is added to EXPECTED_ERROR_CODES so it surfaces verbatim through the API status endpoint instead of being squashed. Frontend follow-up (separate PR): add MISSING_USER_DATA to the status response type and copy a friendly message asking the user to re-export with the User data option enabled.
1 parent 4aa85e5 commit b795af0

1 file changed

Lines changed: 15 additions & 7 deletions

File tree

src/tasks.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -209,14 +209,22 @@ def read_analytics_file(package_status_id, package_id, link, session):
209209
All this data will be useful to parse more complex things later.
210210
'''
211211

212-
user_path = find_user_root(zip.namelist())
213-
if not user_path:
214-
# Fallback to traditional paths
212+
user_root = find_user_root(zip.namelist())
213+
if user_root:
214+
user_path = f'{user_root}/user.json'
215+
elif 'Account/user.json' in zip.namelist():
215216
user_path = 'Account/user.json'
216-
if user_path not in zip.namelist() and 'account/user.json' in zip.namelist():
217-
user_path = 'account/user.json'
217+
elif 'account/user.json' in zip.namelist():
218+
user_path = 'account/user.json'
218219
else:
219-
user_path = f'{user_path}/user.json'
220+
# Discord exports drop user.json (and the entire Account folder)
221+
# entirely when the user un-ticks the "User data" option in the
222+
# request form. Without it the package has no owner identity to
223+
# anchor the analysis on, so there's nothing useful to compute.
224+
# Surface this as a distinct code so the UI can prompt them to
225+
# re-export with that option enabled instead of bouncing them
226+
# with the generic UNKNOWN_ERROR.
227+
raise Exception('MISSING_USER_DATA')
220228
user_content = zip.open(user_path)
221229
user_json = orjson.loads(user_content.read())
222230
user_data = {
@@ -993,7 +1001,7 @@ def process_package(package_status_id, package_id, link, worker_name='regular_pr
9931001
# just the string 'EXPIRED_LINK' (Python tuples need a comma);
9941002
# the `in` check then accidentally did substring match on a
9951003
# single code, hiding INVALID_LINK behind UNKNOWN_ERROR.
996-
EXPECTED_ERROR_CODES = ('EXPIRED_LINK', 'INVALID_LINK')
1004+
EXPECTED_ERROR_CODES = ('EXPIRED_LINK', 'INVALID_LINK', 'MISSING_USER_DATA')
9971005
current = str(e)
9981006
e_traceback = None
9991007
if current not in EXPECTED_ERROR_CODES:

0 commit comments

Comments
 (0)