From fa6eed249e5a70a6acddc97598b5ff04dcd4d27f Mon Sep 17 00:00:00 2001 From: Brigs Date: Tue, 11 Aug 2026 14:46:46 -0400 Subject: [PATCH] Skip non-Messenger JSONs in get_fb_messages instead of crashing The artifact's glob is */*.json, so in any return package it matches every JSON file, then assumed the Facebook Messenger export shape. On a Google Takeout the first foreign JSON killed the whole artifact: a top-level list raised AttributeError on .get, and a dict without a participants list raised TypeError on participants[0]. Found sweeping a newly registered 2021 Google Takeout corpus. Guard the shape instead: skip files that fail to parse as JSON, are not a dict, or lack a non-empty participants list and a messages list. Real Messenger exports parse unchanged (validated with a Messenger-shaped export round-trip: 2 messages, conversation columns intact - shape-verified, not corpus-verified, since no registered corpus carries a Messenger E2E export yet). The full Takeout sweep goes from an artifact-killing traceback to a clean run with zero error lines. Co-Authored-By: Claude Opus 4.8 --- scripts/artifacts/facebookE2EMessages.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/scripts/artifacts/facebookE2EMessages.py b/scripts/artifacts/facebookE2EMessages.py index ccbb9a5..771d29f 100755 --- a/scripts/artifacts/facebookE2EMessages.py +++ b/scripts/artifacts/facebookE2EMessages.py @@ -45,16 +45,27 @@ def get_fb_messages(context): if filename.endswith('.json'): with open(file_found, "r", encoding='utf-8') as fp: - deserialized = json.load(fp) + try: + deserialized = json.load(fp) + except (json.JSONDecodeError, UnicodeDecodeError): + continue + # the glob matches every JSON in a return package; only process + # files with the Messenger export shape + if not isinstance(deserialized, dict): + continue participants = deserialized.get('participants') + messages = deserialized.get('messages') + if not isinstance(participants, list) or not participants \ + or not isinstance(messages, list): + continue owner = participants[0] without_owner = [p for p in participants if p != owner] without_owner = ", ".join(without_owner) thread = deserialized.get('threadName') - for x in deserialized['messages']: + for x in messages: sender_name = x.get('senderName', '') unsent = x.get('isUnsent', '') timestamp = x.get('timestamp', '')