fix(yt-dlp): upgrade a stale copy before import, stop misrouting 403s to streamlink - #4
Open
AdinathChaudhari wants to merge 1 commit into
Open
AdinathChaudhari wants to merge 1 commit into
AdinathChaudhari wants to merge 1 commit into
Conversation
… to streamlink A yt-dlp more than a couple of weeks old still lists formats correctly and then dies partway through the transfer with a bare HTTP 403 — the site rotated its player and the signatures the old copy computes no longer validate. ensure_yt_dlp() only ever installed a *missing* copy, so a working install silently rotted. - Read the installed version with importlib.metadata (no package import) and pip install --upgrade when it is older than YT_DLP_MAX_AGE_DAYS (14). This has to run before the first `import yt_dlp`: a package replaced underneath a live process is not picked up by a re-import, so a mid-run upgrade cannot help. - A failed pip no longer raises; the run continues on whatever is installed, and a genuinely missing yt-dlp now exits with an install hint instead of a traceback. - On a download failure, _looks_stale() recognises the CDN-rejection signatures. When one hits a URL a specific (non-generic) extractor claimed, the media was found and the transfer was refused, so streamlink cannot help — it installs 8 MB of dependencies and ends in "No plugin can handle URL". Print the upgrade command instead. Every other download error still falls through to streamlink. Verified against a real URL that reproduced the 403: fails on 2026.07.04, downloads complete on 2026.08.19. Both new branches exercised — a stale version triggers the upgrade and a current one does not; a 403 on a known extractor skips streamlink while an unrelated error still reaches it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The failure
A download would list every quality correctly, start, and then stop partway with a bare
HTTP Error 403: Forbidden. anydl then announced "yt-dlp can't grab this directly", installed~8 MB of streamlink dependencies, and finished with
No plugin can handle URL.Both halves of that were wrong. The 403 was a stale yt-dlp — the site had rotated its player
and the signatures the old copy computes no longer validate. And streamlink was never going to
help: the media was found, the CDN just refused the transfer.
Root cause
ensure_yt_dlp()only installed yt-dlp when it was missing. A working install was nevertouched again, so it quietly rotted — and these breakages land every few weeks.
Changes
1. Upgrade a stale yt-dlp before the import.
Read the installed version with
importlib.metadata(which doesn't import the package), andpip install --upgradewhen it's older thanYT_DLP_MAX_AGE_DAYS(14). This has to happenbefore the first
import yt_dlp— a package swapped out underneath a running process isn'tpicked up by a re-import, so there's no mid-run rescue. A failed
pipprints and continues onwhatever is installed rather than aborting; a genuinely missing yt-dlp now exits with an install
hint instead of a traceback.
2. Don't route a CDN rejection to streamlink.
_looks_stale()matches the 403 / "unable to download video data" / "requested format is notavailable" signatures. When one of those hits a URL that a specific (non-generic) extractor
claimed, print the upgrade command instead of the streamlink detour. Every other download
error still falls through to streamlink — the never-a-dead-end path is intact.
Verification
Reproduced against a real URL that was failing:
Both new branches exercised directly, with the streamlink call stubbed to see which path is taken:
pip install --upgrade yt-dlpcalled; current version → no pip callknown_extractor()re-checked on real URLs (it correctly rejects malformed IDs, which is whatmakes the guard safe to gate on).