youtube-dl: [YouTube] TypeError: '>' not supported between instances of 'int' and 'NoneType'

Checklist

  • I’m reporting a broken site support
  • I’ve verified that I’m running youtube-dl version 2021.12.17
  • I’ve checked that all provided URLs are alive and playable in a browser
  • I’ve checked that all URLs and arguments with special characters are properly quoted or escaped
  • I’ve searched the bugtracker for similar issues including closed ones

Verbose log

[debug] System config: []
[debug] User config: []
[debug] Custom config: []
[debug] Command-line args: […]
[debug] Encodings: locale UTF-8, fs utf-8, out utf-8, pref UTF-8
[debug] youtube-dl version 2021.12.17
[debug] Git HEAD: e52e8b811
[debug] Python version 3.8.10 (CPython) - Linux-5.8.0-44-lowlatency-x86_64-with-glibc2.29
[debug] exe versions: ffmpeg 4.2.7, ffprobe 4.2.7
[debug] Proxy map: {…}
[youtube] t-hR-TZJT2U: Downloading webpage
[youtube] t-hR-TZJT2U: Downloading MPD manifest
WARNING: [youtube] Unable to decode n-parameter: download likely to be throttled (Failed to evaluate 0 > None (caused by TypeError("'>' not supported between instances of 'int' and 'NoneType'")); please report this issue on https://yt-dl.org/bug . Make sure you are using the latest version; see  https://yt-dl.org/update  on how to update. Be sure to call youtube-dl with the --verbose flag and include its complete output. Traceback (most recent call last):
  File "/mnt/…/youtube_dl/jsinterp.py", line 203, in _operator
    return opfunc(left_val, right_val)
TypeError: '>' not supported between instances of 'int' and 'NoneType'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
…
  File "/mnt/…/youtube_dl/jsinterp.py", line 590, in interpret_expression
    ret, should_return = self.interpret_statement(expr, local_vars, allow_recursion)
  File "/mnt/…/youtube_dl/jsinterp.py", line 454, in interpret_statement
    return self._operator(op, 0 if left_val is None else left_val,
  File "/mnt/…/youtube_dl/jsinterp.py", line 205, in _operator
    raise self.Exception('Failed to evaluate {left_val!r} {op} {right_val!r}'.format(**locals()), expr, cause=e)
youtube_dl.jsinterp.JSInterpreter.Exception: Failed to evaluate 0 > None (caused by TypeError("'>' not supported between instances of 'int' and 'NoneType'")); please report this issue on https://yt-dl.org/bug . Make sure you are using the latest version; see  https://yt-dl.org/update  on how to update. Be sure to call youtube-dl with the --verbose flag and include its complete output.
)

Description

Download seems to work nonetheless.

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 1
  • Comments: 17 (14 by maintainers)

Commits related to this issue

Most upvoted comments

@dirkf, thanks for the commit b0a60ce.

@pukkandan and @dirkf, the amount of hard-work you people put-in to keep youtube-dl/yt-dlp alive is simply awesome…!

Ofc, what comes to mind is the process by which this nonsense (here I mean n-sig rather than JS in general) is developed. Is there an obfuscated JS department in YT with a calendar reminder to turn out a new version every so often, or do they get each lot of interns/new grads to work up a set of challenges that can be rolled out randomly through the year, or …?

@pukkandan does the incredible stuff: I just nick it!

This is what I meant that Youtube can make it much harder for us if the signature function starts to rely on JS’s type coersion. Luckily it wasn’t that bad this time. But if they double down on this, we will be forced to define equivalent classes for each JS object rather than approximating with Python builtins. Add some try-catch blocks to the mix, and only a proper intrpretter can handle all the edge cases

@dirkf Thanks for your detailed explanation. Mine was just a dirty method from a layman-point-of-view to temporarily get rid of those error-msgs flooding the terminal…

I have picked-up your commits b80413b and 41631a3 from #31175, rebuilt youtube-dl (both py2.7 and py3.6 versions). No errors, and download speeds are quite good.

Thanks for your incredible work.

Previously the escape 0 if val is None else val was only used for the LHS of a binary operation, but PR #31175 does it right, for the weird definition of “right” that JS expects.

The key message from SO:

If it’s your code, figure out how you’re getting None when you expect a number and stop that from happening.

If it’s someone else’s code, find out the conditions under which it gives None and determine a sensible value to use for that, …

JS is happy to compare null against numeric values, so Python’s x < 0 is not the same as JS’s. Naïvely mapping JS null to None and < to < (aka operator.lt) causes this runtime error if the interpreter is given such an expression.

Here are some JS comparisons with their results:

[null > 0, null < 0, null == 0, null === 0]
/*
false,false,false,false
*/

[undefined > 0, undefined < 0, undefined == 0, undefined === 0]
/*
false,false,false,false
*/

[undefined > null, undefined < null, undefined == null, undefined === null]
/*
false,false,true,false
*/

/* BEST OF ALL */
[null >= 0, null <= 0]
/*
true,true
*/

So null is not 0, nor less than 0 nor greater than 0, yet it’s greater than or equal to 0 and less than or equal to 0: perhaps not the best part of Brendan Eich’s busy week in 1995.

Luckily the same devil-may-care attitude to consistency is maintained even today, as evidenced by the recent addition of a ** operator with undefined ** 0 == 1: how could it not be undefined? (The answer is that the much older Math.pow(x, 0) does this too, when x is undefined and in fact for any x.)

You’d have to go through more hoops to get Python 2.7 running your yt-dl, anyway.

Indeed, I had to edit the shebang line of my wrapper script. I didn’t remember I had upgraded it to use python3 yet. Now the warning seems gone and download speed seems to be back to normal. So thanks for reminding me of that extra step!

The problem is with this line 264 of the pretty-printed nsig code:

      6 >= c[104] ? (0, c[22]) ((0, c[1]) ((0, c[5]) (c[13], c[44]), c[76], c[12], c[75]), c[2], (0, c[0]) (((0, c[82]) (c[12]), (0, c[98]) (c[72], c[12])), c[106], (0, c[31]) (c[63], c[35]) > (0, c[102]) (c[ - 120 * Math.pow(7, 2) + 5969], c[82]), c[12], c[10]), c[29], c[21])  : (0, c[81]) ((0, c[40]) (c[10], c[11], (0, c[20]) ()), c[53], (0, c[new Date('31 December 1969 13:15:53 -1045') / 1000]) ((0, c[53]) ((0, c[12]) (c[26]), c[35], c[10], c[275 % Math.pow(new Date('1969-12-31T17:00:02.000-07:00') / 1000, 5) + 9]), c[40], c[67], c[74], (0, c[21]) ()), (0, c[53]) ((0, c[35]) (c[42], c[104]), c[35], c[67], c[48]), (0, c[86]) (c[Math.pow(5, 5) + 17176 + - 20291], c[51]), c[49], c[64], c[42]),

yt-dl is trying to evaluate this part of the line, and the RHS of the ‘>’ is evaluating to None:

(0,c[0])(((0,c[82])(c[12]),(0,c[98])(c[72],c[12])),c[106],(0,c[31])(c[63],c[35])>(0,c[102])(c[-120*Math.pow(7,2)+5969],c[82]),c[12],c[10])

Here c[102] is a number, so something went wrong way back, something that behaves differently in Py2.7 (no error, though I didn’t check the download speed), Py3.5, Py 3.8+.