{"record":{"id":"e0ad4abb80572959","repo":"ytdl-org/youtube-dl","slug":"received-invalid-json-data","errorCode":null,"errorMessage":"Received invalid JSON data","messagePattern":"Received invalid JSON data","errorType":"exception","errorClass":"ExtractorError","httpStatus":null,"severity":"error","filePath":"youtube_dl/extractor/bigo.py","lineNumber":38,"sourceCode":"        },\n        'skip': 'livestream',\n    }, {\n        'url': 'https://www.bigo.tv/th/Tarlerm1304',\n        'only_matching': True,\n    }, {\n        'url': 'https://bigo.tv/115976881',\n        'only_matching': True,\n    }]\n\n    def _real_extract(self, url):\n        user_id = self._match_id(url)\n\n        info_raw = self._download_json(\n            'https://bigo.tv/studio/getInternalStudioInfo',\n            user_id, data=urlencode_postdata({'siteId': user_id}))\n\n        if not isinstance(info_raw, dict):\n            raise ExtractorError('Received invalid JSON data')\n        if info_raw.get('code'):\n            raise ExtractorError(\n                'Bigo says: %s (code %s)' % (info_raw.get('msg'), info_raw.get('code')), expected=True)\n        info = info_raw.get('data') or {}\n\n        if not info.get('alive'):\n            raise ExtractorError('This user is offline.', expected=True)\n\n        return {\n            'id': info.get('roomId') or user_id,\n            'title': info.get('roomTopic') or info.get('nick_name') or user_id,\n            'formats': [{\n                'url': info.get('hls_src'),\n                'ext': 'mp4',\n                'protocol': 'm3u8',\n            }],\n            'thumbnail': info.get('snapshot'),\n            'uploader': info.get('nick_name'),","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/extractor/bigo.py#L20-L56","documentation":"Raised by BigoIE._real_extract when the POST to https://bigo.tv/studio/getInternalStudioInfo (with siteId=<user_id>) succeeds at the HTTP level but the parsed JSON body is not an object — e.g. a JSON string, number, array, or null. _download_json only guarantees valid JSON, not a dict shape, so the extractor guards the type before accessing keys and fails hard (not expected=True) because a non-dict response means an API contract break.","triggerScenarios":"The getInternalStudioInfo endpoint returning a scalar/array JSON body: API version changes, WAF/CDN interference returning a JSON-encoded string like \"ok\", or an A/B backend. Any user_id where the response decodes to a non-dict triggers it before any field checks run.","commonSituations":"Bigo changing its internal studio API response envelope; anti-bot layers returning terse JSON strings; requesting with malformed siteId that elicits a non-object error body; extractor drift after site updates.","solutions":["Reproduce the POST manually (curl -d 'siteId=<id>') and inspect the raw body to see what shape Bigo now returns.","If the shape moved (e.g. data now nested or returned as a JSON string), update the isinstance check and field access in bigo.py:38.","Confirm the user_id captured from the URL is a valid numeric Bigo id.","If the endpoint was replaced, locate the new studio-info endpoint in the site's JS and retarget _download_json."],"exampleFix":"// before\ninfo_raw = self._download_json('https://bigo.tv/studio/getInternalStudioInfo', user_id, data=urlencode_postdata({'siteId': user_id}))\nif not isinstance(info_raw, dict):\n    raise ExtractorError('Received invalid JSON data')\n\n// after: include the actual type/body to speed diagnosis\nif not isinstance(info_raw, dict):\n    raise ExtractorError('Bigo returned unexpected JSON (type: %s): %.200r' % (type(info_raw).__name__, info_raw))","handlingStrategy":"type-guard","validationCode":"import requests\n\ndef bigo_api_returns_dict(user_id):\n    r = requests.post('https://bigo.tv/studio/getInternalStudioInfo', data={'siteId': user_id})\n    try:\n        body = r.json()\n    except ValueError:\n        return False\n    return isinstance(body, dict)","typeGuard":"def is_bigo_dict_response(body):\n    return isinstance(body, dict)","tryCatchPattern":"try:\n    ydl.extract_info('https://bigo.tv/%s' % user_id)\nexcept ExtractorError as e:\n    if str(e) == 'Received invalid JSON data':\n        # API contract break; not transient - inspect the endpoint manually\n        raise ApiSchemaChanged('bigo getInternalStudioInfo no longer returns a dict') from e\n    raise","preventionTips":["Probe the endpoint once per session and abort early if the shape is not a dict.","Pin extractor versions in production tooling so silent site changes surface as explicit failures.","Log raw response bodies on schema-guard failures to speed patching."],"tags":["bigo","json-validation","type-guard","api-contract","extractor"],"backgroundTag":null,"analyzedSha":"956b8c585591b401a543e409accb163eeaaa1193","analyzedAt":"2026-08-14T18:59:47.863Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}