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

traceback.format_exc() (dynamic; surfaces in 'Unable to deco

Error message

traceback.format_exc() (dynamic; surfaces in 'Unable to decode n-parameter' warning)

What it means

Not a standalone raise: inside extract_nsig (built by _extract_n_function_from_code) any non-JSInterpreter exception from executing the extracted JS function is re-raised as JSInterpreter.Exception(traceback.format_exc(), cause=e). The full Python traceback string becomes the exception message, which later surfaces in the 'Unable to decode n-parameter: expect download to be blocked or throttled' warning emitted by _decrypt_nsig's handler.

Source

Thrown at youtube_dl/extractor/youtube.py:2120

    def _extract_n_function_code_jsi(self, video_id, jsi, player_id=None, player_url=None):
        func_name = self._extract_n_function_name(jsi.code)

        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)

View on GitHub (pinned to 956b8c5855)

Solutions

  1. Update youtube-dl/yt-dlp so both the extraction pattern and JS interpreter handle the current player.
  2. Read the embedded traceback text in the warning — it names the actual Python error inside the interpreter and points at the unsupported operation.
  3. Clear the cached player/nsig data (cache dir) so a fresh function is extracted after updating.
  4. If downloads only become slow (not broken), the warning can be tolerated while awaiting an upstream fix.
Defensive patterns

Strategy: fallback

Try / catch

try:
    ret = extract_nsig(n)
except JSInterpreter.Exception as e:
    # message contains a full Python traceback; log for diagnosis, keep throttled URL
    log_warning('Unable to decode n-parameter: %s' % str(e).splitlines()[-1])
    return None  # caller falls back to the un-decrypted URL

Prevention

When it happens

Trigger: Executing the extracted nsig JS function raises an unexpected Python error (type error, key error in the JS interpreter, etc.) for some input n values — e.g. interpreter gaps hitting new JS syntax, or a function that behaves differently for edge-case signatures.

Common situations: A new player version uses JS features the bundled interpreter mishandles; only some n values hit the failing branch, so most downloads work but occasional ones warn; stale cached nsig functions being reused against a new player.

Understand the failure class

Related errors


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