{"record":{"id":"fec04d73959186d8","repo":"ytdl-org/youtube-dl","slug":"s-fec04d","errorCode":null,"errorMessage":"%s","messagePattern":"%s","errorType":"exception","errorClass":"ExtractorError","httpStatus":null,"severity":"error","filePath":"youtube_dl/extractor/shahid.py","lineNumber":33,"sourceCode":"    parse_iso8601,\n    str_or_none,\n    urlencode_postdata,\n)\n\n\nclass ShahidBaseIE(AWSIE):\n    _AWS_PROXY_HOST = 'api2.shahid.net'\n    _AWS_API_KEY = '2RRtuMHx95aNI1Kvtn2rChEuwsCogUd4samGPjLh'\n    _VALID_URL_BASE = r'https?://shahid\\.mbc\\.net/[a-z]{2}/'\n\n    def _handle_error(self, e):\n        fail_data = self._parse_json(\n            e.cause.read().decode('utf-8'), None, fatal=False)\n        if fail_data:\n            faults = fail_data.get('faults', [])\n            faults_message = ', '.join([clean_html(fault['userMessage']) for fault in faults if fault.get('userMessage')])\n            if faults_message:\n                raise ExtractorError(faults_message, expected=True)\n\n    def _call_api(self, path, video_id, request=None):\n        query = {}\n        if request:\n            query['request'] = json.dumps(request)\n        try:\n            return self._aws_execute_api({\n                'uri': '/proxy/v2/' + path,\n                'access_key': 'AKIAI6X4TYCIXM2B7MUQ',\n                'secret_key': '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',\n            }, video_id, query)\n        except ExtractorError as e:\n            if isinstance(e.cause, compat_HTTPError):\n                self._handle_error(e)\n            raise\n\n\nclass ShahidIE(ShahidBaseIE):","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/extractor/shahid.py#L15-L51","documentation":"Raised from ShahidBaseIE._handle_error when an AWS API Gateway call to api2.shahid.net fails and the HTTP error body parses as JSON containing a 'faults' array. Each fault's 'userMessage' (cleaned of HTML) is joined into one message and re-raised as an expected ExtractorError. It converts opaque AWS gateway faults into readable, user-facing Shahid API errors.","triggerScenarios":"Any _call_api invocation (e.g. playout/new/url/<id>, getuser or product endpoints) where _aws_execute_api raises ExtractorError whose cause is an HTTPError whose body has {'faults': [{'userMessage': ...}]}. Common fault causes: expired/invalid device session, DRM-restricted asset requiring subscription, geo restriction, or an expired API key/signature.","commonSituations":"Expired Shahid session token (the API demands a fresh deviceId/sessionId); trying to play premium/DRM content on a free account; the hard-coded AWS access key/secret in the extractor being rotated by MBC so every call is rejected with a signature fault; region blocks outside the MBC footprint.","solutions":["Read the userMessage text: it names the real fault (session, entitlement, geo, or auth).","If it is a session/device fault, re-run with a clean cache so the extractor regenerates its session (--no-cache-dir / delete ~/.cache/youtube-dl).","If the fault is entitlement/DRM, the asset requires a Shahid subscription and cannot be downloaded anonymously.","If every request faults with an auth/signature message, the extractor's embedded AWS credentials are stale - update to the latest youtube-dl/yt-dlp where new keys are shipped.","If geo-blocked, use an appropriate VPN region or choose another source."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    result = shahid_call(path, video_id)\nexcept ExtractorError as e:\n    if e.expected and 'session' in str(e).lower():\n        clear_cache(); retry_once()\n    else:\n        log_fault_message(str(e))","preventionTips":["Clear the youtube-dl cache before Shahid batches so sessions are re-created.","Treat any fault mentioning signature/auth as 'extractor outdated' - update immediately.","Do not retry entitlement/DRM faults; they are deterministic."],"tags":["aws-api-gateway","shahid","session-expiry","extractor","drm"],"backgroundTag":null,"analyzedSha":"956b8c585591b401a543e409accb163eeaaa1193","analyzedAt":"2026-08-14T18:59:47.863Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}