{"record":{"id":"2bef16fb5757f2b7","repo":"ytdl-org/youtube-dl","slug":"signature-function-returned-an-exception","errorCode":null,"errorMessage":"Signature function returned an exception","messagePattern":"Signature function returned an exception","errorType":"exception","errorClass":"JSInterpreter.Exception","httpStatus":null,"severity":"warning","filePath":"youtube_dl/extractor/youtube.py","lineNumber":2123,"sourceCode":"\n        func_code = self._extract_sig_fn(jsi, func_name)\n        if player_url:\n            self._store_player_data_to_cache('nsig', player_url, func_code)\n        return jsi, player_id, func_code\n\n    def _extract_n_function_from_code(self, jsi, func_code):\n        func = jsi.extract_function_from_code(*func_code)\n\n        def extract_nsig(s):\n            try:\n                ret = func([s], kwargs={'_ytdl_do_not_return': s})\n            except JSInterpreter.Exception:\n                raise\n            except Exception as e:\n                raise JSInterpreter.Exception(traceback.format_exc(), cause=e)\n\n            if ret.startswith('enhanced_except_') or ret.endswith(s):\n                raise JSInterpreter.Exception('Signature function returned an exception')\n            return ret\n\n        return extract_nsig\n\n    def _unthrottle_format_urls(self, video_id, player_url, *formats):\n\n        def decrypt_nsig(n):\n            return self._cached(self._decrypt_nsig, 'nsig', n, player_url)\n\n        for fmt in formats:\n            n_param = parse_qs(fmt['url']).get('n')\n            if not n_param:\n                continue\n            n_param = n_param[-1]\n            n_response = decrypt_nsig(n_param)(n_param, video_id, player_url)\n            if n_response is None:\n                # give up and forget cached data if descrambling failed\n                self._remove_player_data_from_cache('nsig', player_url)","sourceCodeStart":2105,"sourceCodeEnd":2141,"githubUrl":"https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/extractor/youtube.py#L2105-L2141","documentation":"Raised as JSInterpreter.Exception inside extract_nsig when the executed nsig function returns a value that starts with 'enhanced_except_' (the JS function's own error marker) or ends with the input string s (meaning the 'decryption' is an identity — it failed to transform the parameter). Both outcomes mean the extracted function did not actually decrypt the n parameter.","triggerScenarios":"The regex/interpreter extracted the wrong function or partially evaluated it (e.g. matched a decoy function, or the interpreter took an early-return branch), so calling func([s]) yields the input unchanged or the enhanced_except_ marker. Occurs per n-value during _unthrottle_format_urls.","commonSituations":"YouTube adds decoy similarly-named functions or restructures code so the extraction grabs the wrong one; interpreter shortcuts (like the _ytdl_do_not_return guard) reveal identity results; new player versions after youtube-dl's last patch.","solutions":["Update youtube-dl / move to yt-dlp — wrong-function extraction is fixed by pattern updates.","Clear the nsig function cache so a stale wrong function is not reused.","If developing, verify _extract_n_function_code's function identification against the current base.js and test with the known failing n value.","Tolerate the resulting throttle warning short-term: URLs still work, just slower."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"def nsig_result_ok(ret: str, s: str) -> bool:\n    return not (ret.startswith('enhanced_except_') or ret.endswith(s))","typeGuard":null,"tryCatchPattern":"try:\n    ret = extract_nsig(n)\nexcept JSInterpreter.Exception as e:\n    if 'Signature function returned an exception' in str(e):\n        clear_player_cache(player_url)   # wrong function cached\n        return extract_nsig_fresh(n)     # re-extract and retry once\n    raise","preventionTips":["Verify decrypted values differ from input and lack the enhanced_except_ prefix during development.","Invalidate the nsig cache whenever the player version changes to avoid replaying a wrong function."],"tags":["youtube","nsig","wrong-function","js-interpreter"],"backgroundTag":null,"analyzedSha":"956b8c585591b401a543e409accb163eeaaa1193","analyzedAt":"2026-08-14T18:59:47.863Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}