ytdl-org/youtube-dl · warning · JSInterpreter.Exception

Signature function returned an exception

Error message

Signature function returned an exception

What it means

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.

Source

Thrown at youtube_dl/extractor/youtube.py:2123

        func_code = self._extract_sig_fn(jsi, func_name)
        if player_url:
            self._store_player_data_to_cache('nsig', player_url, func_code)
        return jsi, player_id, func_code

    def _extract_n_function_from_code(self, jsi, func_code):
        func = jsi.extract_function_from_code(*func_code)

        def extract_nsig(s):
            try:
                ret = func([s], kwargs={'_ytdl_do_not_return': s})
            except JSInterpreter.Exception:
                raise
            except Exception as e:
                raise JSInterpreter.Exception(traceback.format_exc(), cause=e)

            if ret.startswith('enhanced_except_') or ret.endswith(s):
                raise JSInterpreter.Exception('Signature function returned an exception')
            return ret

        return extract_nsig

    def _unthrottle_format_urls(self, video_id, player_url, *formats):

        def decrypt_nsig(n):
            return self._cached(self._decrypt_nsig, 'nsig', n, player_url)

        for fmt in formats:
            n_param = parse_qs(fmt['url']).get('n')
            if not n_param:
                continue
            n_param = n_param[-1]
            n_response = decrypt_nsig(n_param)(n_param, video_id, player_url)
            if n_response is None:
                # give up and forget cached data if descrambling failed
                self._remove_player_data_from_cache('nsig', player_url)

View on GitHub (pinned to 956b8c5855)

Solutions

  1. Update youtube-dl / move to yt-dlp — wrong-function extraction is fixed by pattern updates.
  2. Clear the nsig function cache so a stale wrong function is not reused.
  3. If developing, verify _extract_n_function_code's function identification against the current base.js and test with the known failing n value.
  4. Tolerate the resulting throttle warning short-term: URLs still work, just slower.
Defensive patterns

Strategy: retry

Validate before calling

def nsig_result_ok(ret: str, s: str) -> bool:
    return not (ret.startswith('enhanced_except_') or ret.endswith(s))

Try / catch

try:
    ret = extract_nsig(n)
except JSInterpreter.Exception as e:
    if 'Signature function returned an exception' in str(e):
        clear_player_cache(player_url)   # wrong function cached
        return extract_nsig_fresh(n)     # re-extract and retry once
    raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of ytdl-org/youtube-dl@956b8c5855 (2026-08-14). Data as JSON: /api/errors/2bef16fb5757f2b7. Report an issue: GitHub.