{"record":{"id":"eb12355c3d38ec92","repo":"ytdl-org/youtube-dl","slug":"s-said-s-eb1235","errorCode":null,"errorMessage":"%s said: %s","messagePattern":"%s said: %s","errorType":"exception","errorClass":"ExtractorError","httpStatus":null,"severity":"error","filePath":"youtube_dl/extractor/kaltura.py","lineNumber":185,"sourceCode":"            if service_mobj:\n                url = smuggle_url(url, {'service_url': service_mobj.group('id')})\n            urls.append(url)\n        return urls\n\n    def _kaltura_api_call(self, video_id, actions, service_url=None, *args, **kwargs):\n        params = actions[0]\n        if len(actions) > 1:\n            for i, a in enumerate(actions[1:], start=1):\n                for k, v in a.items():\n                    params['%d:%s' % (i, k)] = v\n\n        data = self._download_json(\n            (service_url or self._SERVICE_URL) + self._SERVICE_BASE,\n            video_id, query=params, *args, **kwargs)\n\n        status = data if len(actions) == 1 else data[0]\n        if status.get('objectType') == 'KalturaAPIException':\n            raise ExtractorError(\n                '%s said: %s' % (self.IE_NAME, status['message']))\n\n        return data\n\n    def _get_video_info(self, video_id, partner_id, service_url=None):\n        actions = [\n            {\n                'action': 'null',\n                'apiVersion': '3.1.5',\n                'clientTag': 'kdp:v3.8.5',\n                'format': 1,  # JSON, 2 = XML, 3 = PHP\n                'service': 'multirequest',\n            },\n            {\n                'expiry': 86400,\n                'service': 'session',\n                'action': 'startWidgetSession',\n                'widgetId': '_%s' % partner_id,","sourceCodeStart":167,"sourceCodeEnd":203,"githubUrl":"https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/extractor/kaltura.py#L167-L203","documentation":"Raised by the Kaltura extractor when the multirequest API response's first object has objectType 'KalturaAPIException'. The exception's 'message' field from Kaltura's API is forwarded with the extractor name as prefix - typical messages are 'Access denied', 'Entry not found', or KS (session) errors.","triggerScenarios":"A Kaltura partner API call (base <service_url>/api_v3/index.php?service=multirequest) where Kaltura rejects the request: invalid/expired KS session token, entry_id that does not exist for that partner_id, or lacking permissions for the requested flavors.","commonSituations":"Embed URLs copied from a different partner context (mismatched partner_id/entry_id), expired smuggled KS tokens, or access-controlled media on university/corporate Kaltura portals.","solutions":["Read the forwarded Kaltura message - it states the exact API rejection.","Verify the embed URL is the original one from the page (partner id and entry id must match).","For KS/session errors, re-extract from the fresh player page so a new session token is obtained.","Update youtube-dl/yt-dlp for API version changes."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    ydl.extract_info(kaltura_url)\nexcept ExtractorError as e:\n    msg = str(e)\n    if 'not found' in msg or 'Access denied' in msg:\n        skip_permanently(kaltura_url)\n    elif 'KS' in msg or 'session' in msg.lower():\n        refresh_page_and_retry(kaltura_url)  # obtain a new session","preventionTips":["Extract embed URLs fresh from the hosting page so partner_id/entry_id/KS stay consistent.","Classify Kaltura messages (entry-not-found vs access-denied vs session-expired) before retrying.","Never cache KS session tokens - they expire."],"tags":["api","extractor","kaltura","entitlement","session","error-forwarding"],"backgroundTag":null,"analyzedSha":"956b8c585591b401a543e409accb163eeaaa1193","analyzedAt":"2026-08-14T18:59:47.863Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}