{"record":{"id":"c4e520bf86db6065","repo":"ytdl-org/youtube-dl","slug":"mediasite-says-s","errorCode":null,"errorMessage":"Mediasite says: %s","messagePattern":"Mediasite says: (.+?)","errorType":"exception","errorClass":"ExtractorError","httpStatus":null,"severity":"error","filePath":"youtube_dl/extractor/mediasite.py","lineNumber":158,"sourceCode":"            '%s/GetPlayerOptions' % service_path, resource_id,\n            headers={\n                'Content-type': 'application/json; charset=utf-8',\n                'X-Requested-With': 'XMLHttpRequest',\n            },\n            data=json.dumps({\n                'getPlayerOptionsRequest': {\n                    'ResourceId': resource_id,\n                    'QueryString': query,\n                    'UrlReferrer': data.get('UrlReferrer', ''),\n                    'UseScreenReader': False,\n                }\n            }).encode('utf-8'))['d']\n\n        presentation = player_options['Presentation']\n        title = presentation['Title']\n\n        if presentation is None:\n            raise ExtractorError(\n                'Mediasite says: %s' % player_options['PlayerPresentationStatusMessage'],\n                expected=True)\n\n        thumbnails = []\n        formats = []\n        for snum, Stream in enumerate(presentation['Streams']):\n            stream_type = Stream.get('StreamType')\n            if stream_type is None:\n                continue\n\n            video_urls = Stream.get('VideoUrls')\n            if not isinstance(video_urls, list):\n                video_urls = []\n\n            stream_id = self._STREAM_TYPES.get(\n                stream_type, 'type%u' % stream_type)\n\n            stream_formats = []","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/extractor/mediasite.py#L140-L176","documentation":"Raised by the Mediasite extractor when the getPlayerOptions JSON-RPC response has a null 'Presentation' object, meaning the requested resource id has no playable presentation. The message embeds PlayerPresentationStatusMessage, the site's own status text. Note the guard is written after `presentation['Title']` is already dereferenced on the line above, so in practice this code path can crash with a TypeError before the raise — a known code-order defect.","triggerScenarios":"POST of getPlayerOptionsRequest for a resource id returns d.PlayerPresentationStatusMessage with a failed status and Presentation == null; accessing presentation['Title'] first means a None presentation usually raises TypeError ('NoneType' object is not subscriptable) instead of this ExtractorError.","commonSituations":"Mediasite recording deleted or not yet processed; resource id from an old bookmark; permission-restricted presentation requiring institution auth; the Title-before-None-check ordering bug turning every genuine case into an unhandled TypeError.","solutions":["Verify the Mediasite presentation URL in a browser and confirm the recording is published.","Pass institutional cookies (--cookies) if the presentation requires authentication.","Update youtube-dl / switch to yt-dlp where the None-check ordering is fixed so the real status message is shown.","Report the URL if the presentation is public yet still fails, so the extractor's player-options handling can be updated."],"exampleFix":"// before\npresentation = player_options['Presentation']\ntitle = presentation['Title']\n\nif presentation is None:\n    raise ExtractorError('Mediasite says: %s' % player_options['PlayerPresentationStatusMessage'], expected=True)\n\n// after (check before dereferencing)\npresentation = player_options['Presentation']\nif presentation is None:\n    raise ExtractorError('Mediasite says: %s' % player_options['PlayerPresentationStatusMessage'], expected=True)\ntitle = presentation['Title']","handlingStrategy":"validation","validationCode":null,"typeGuard":"def mediasite_presentation_missing(player_options):\n    return not isinstance(player_options, dict) or player_options.get('Presentation') is None","tryCatchPattern":"try:\n    info = ydl.extract_info(url, download=False)\nexcept ExtractorError as e:\n    if 'Mediasite says:' in str(e):\n        reason = str(e).split('says:', 1)[1].strip()\n        handle_status(reason)  # 'Unauthorized', 'NotFound', etc.\n    else:\n        raise","preventionTips":["Confirm presentations are published and public before extraction.","Pass institutional session cookies for auth-protected Mediasite deployments.","Watch for the pre-existing None-dereference bug: a TypeError here means the same root cause hit the broken code path."],"tags":["json-rpc","null-presentation","ordering-bug","expected-error"],"backgroundTag":null,"analyzedSha":"956b8c585591b401a543e409accb163eeaaa1193","analyzedAt":"2026-08-14T18:59:47.863Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}