{"record":{"id":"3e4acba4ab8dd1ee","repo":"ytdl-org/youtube-dl","slug":"join-e-message-for-e-in-entitlement-issue","errorCode":null,"errorMessage":"', '.join([e['message'] for e in entitlement_issues])","messagePattern":"', '\\.join\\(\\[e\\['message'\\] for e in entitlement_issues\\]\\)","errorType":"exception","errorClass":"ExtractorError","httpStatus":null,"severity":"error","filePath":"youtube_dl/extractor/fox.py","lineNumber":78,"sourceCode":"            'X-Api-Key': self._API_KEY,\n        }\n        if self._access_token:\n            headers['Authorization'] = 'Bearer ' + self._access_token\n        try:\n            return self._download_json(\n                'https://api2.fox.com/v2.0/' + path,\n                video_id, data=data, headers=headers)\n        except ExtractorError as e:\n            if isinstance(e.cause, compat_HTTPError) and e.cause.code == 403:\n                entitlement_issues = self._parse_json(\n                    e.cause.read().decode(), video_id)['entitlementIssues']\n                for e in entitlement_issues:\n                    if e.get('errorCode') == 1005:\n                        raise ExtractorError(\n                            'This video is only available via cable service provider '\n                            'subscription. You may want to use --cookies.', expected=True)\n                messages = ', '.join([e['message'] for e in entitlement_issues])\n                raise ExtractorError(messages, expected=True)\n            raise\n\n    def _real_initialize(self):\n        if not self._access_token:\n            mvpd_auth = self._get_cookies(self._HOME_PAGE_URL).get('mvpd-auth')\n            if mvpd_auth:\n                self._access_token = (self._parse_json(compat_urllib_parse_unquote(\n                    mvpd_auth.value), None, fatal=False) or {}).get('accessToken')\n            if not self._access_token:\n                self._access_token = self._call_api(\n                    'login', None, json.dumps({\n                        'deviceId': compat_str(uuid.uuid4()),\n                    }).encode())['accessToken']\n\n    def _real_extract(self, url):\n        video_id = self._match_id(url)\n\n        video = self._call_api('vodplayer/' + video_id, video_id)","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/extractor/fox.py#L60-L96","documentation":"Raised by the FOX extractor when a 403 from api2.fox.com lists entitlementIssues but NONE of them carries errorCode 1005. All issue messages are joined with ', ' and re-raised as an expected error. This covers every non-'cable subscription' entitlement rejection: not entitled to the specific show, device/session issues, or account-level restrictions.","triggerScenarios":"The 403 body parses successfully, the loop over entitlement_issues finds no errorCode 1005, and the joined 'message' fields are raised. Typical: a FOX account is authenticated but the content needs a different tier/package, the show is exclusive to another network, or the session token was rejected.","commonSituations":"Cookies from an account without the right package; FOX moving content to FOX One/FX+ tiers; stale access tokens after provider re-authentication.","solutions":["Read the joined messages — they state the actual entitlement problem (e.g. 'not entitled to content')","Re-export fresh cookies from a browser where the show plays successfully","Confirm the content's availability tier on fox.com and that your plan includes it","Ensure a US IP, since geo failures can surface as entitlement issues on this API"],"exampleFix":"# before\nyoutube_dl --cookies old_cookies.txt 'https://www.fox.com/watch/some-show/'\n# ERROR: not entitled to content, session expired\n\n# after\n# log in to fox.com in browser, verify playback, re-export cookies\nyoutube_dl --cookies fresh_cookies.txt 'https://www.fox.com/watch/some-show/'","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    ydl.extract_info(url)\nexcept ExtractorError as e:\n    if 'entitlement' in str(e) or 'entitled' in str(e):\n        log_and_alert_subscriber(e)  # surface joined messages to the user","preventionTips":["Re-export cookies whenever the FOX session is refreshed in-browser","Parse the joined messages programmatically to route to the right fix (tier vs session vs geo)"],"tags":["fox","extractor","entitlement","api-error"],"backgroundTag":null,"analyzedSha":"956b8c585591b401a543e409accb163eeaaa1193","analyzedAt":"2026-08-14T18:59:47.863Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}