TL;DR(中文):v1.5.0 的 doctor 建议写入 --js-runtimes node,但仓库自己的 constraints.txt 钉死的 yt-dlp==2025.5.22 不支持该参数;而且这个旧版对当前 YouTube 已经无法解析。升级 yt-dlp 后一切正常,但再按 -c constraints.txt 重装会把修好的版本降级回坏的。
TL;DR (EN): In v1.5.0, doctor's prescribed yt-dlp config flag (--js-runtimes node) is not supported by the repo's own pinned yt-dlp==2025.5.22; that pin itself also fails against live 2026 YouTube; and re-installing with -c constraints.txt downgrades a user-fixed setup back to broken.
Environment
- agent-reach v1.5.0 (installed from the
v1.5.0 tag), deps installed with pip install -c constraints.txt ... per the header in constraints.txt
- Windows 11 (native), Python 3.14
- Node.js v24 present, no deno (this is what triggers the Node prescription path)
- yt-dlp 2025.5.22 (the constraints pin)
Steps to reproduce
-
Install from tag v1.5.0 honoring the tested pin set → yt-dlp==2025.5.22.
-
Run agent-reach doctor (or agent-reach install) on a machine with Node but without deno → the YouTube channel warns and prescribes writing --js-runtimes node into the yt-dlp config (%APPDATA%\yt-dlp\config on Windows).
-
Apply the prescription exactly as printed → every yt-dlp invocation now fails:
yt-dlp: error: no such option: --js-runtimes
-
Remove the config line → extraction still fails against live YouTube with the pinned version:
ERROR: YoutubeIEContentProviderLogger.debug() got an unexpected keyword argument 'once'
-
pip install -U yt-dlp (tested with 2026.7.4) + re-apply the same prescription → works. Verified end-to-end: video title and .en.vtt auto-subtitles download successfully.
-
Re-run the documented install command with -c constraints.txt → pip downgrades yt-dlp back to 2025.5.22 → broken again.
Expected vs actual
- Expected: the pinned dependency set and doctor's prescriptions are mutually consistent; applying doctor's advice never breaks a channel.
- Actual: the prescription is rejected by the pinned yt-dlp (
no such option: --js-runtimes), and the pin itself can no longer parse 2026 YouTube (YoutubeIEContentProviderLogger.debug() ... 'once').
Minor related observation: doctor can show YouTube as ✅ while extraction is actually broken, because the probe is yt-dlp --version, which succeeds even with an invalid config option or a stale extractor.
Root cause (v1.5.0 tag sources)
constraints.txt:11 → yt-dlp==2025.5.22
agent_reach/channels/youtube.py:57-64 → when Node is the JS runtime, doctor warns and prints the fix command
agent_reach/utils/paths.py:29-46 (render_ytdlp_fix_command) → renders the --js-runtimes node config append
--js-runtimes only exists in newer yt-dlp releases (present in 2026.7.4; rejected by 2025.5.22), so v1.5.0 prescribes a flag its own tested pin cannot parse. Independently, yt-dlp is a rolling extractor — a ~14-month-old pin cannot track YouTube's changes.
Suggested fix
- Bump the
constraints.txt yt-dlp pin to a current release (≥ 2026.x), and ideally add a CI smoke test that runs the pinned yt-dlp against a live YouTube URL so a dead pin is caught automatically; or
- Gate the
--js-runtimes prescription on the detected yt-dlp version (only prescribe when the flag is supported), and have doctor warn when the installed yt-dlp is significantly stale.
- Docs: note that re-installing with
-c constraints.txt will downgrade a user-upgraded yt-dlp (easy footgun after a manual fix).
Related: #378 mentions the stale yt-dlp pin in passing (security/staleness angle); this issue is the concrete functional break plus the self-contradicting doctor prescription.
TL;DR (EN): In v1.5.0,
doctor's prescribed yt-dlp config flag (--js-runtimes node) is not supported by the repo's own pinnedyt-dlp==2025.5.22; that pin itself also fails against live 2026 YouTube; and re-installing with-c constraints.txtdowngrades a user-fixed setup back to broken.Environment
v1.5.0tag), deps installed withpip install -c constraints.txt ...per the header inconstraints.txtSteps to reproduce
Install from tag
v1.5.0honoring the tested pin set →yt-dlp==2025.5.22.Run
agent-reach doctor(oragent-reach install) on a machine with Node but without deno → the YouTube channel warns and prescribes writing--js-runtimes nodeinto the yt-dlp config (%APPDATA%\yt-dlp\configon Windows).Apply the prescription exactly as printed → every yt-dlp invocation now fails:
Remove the config line → extraction still fails against live YouTube with the pinned version:
pip install -U yt-dlp(tested with 2026.7.4) + re-apply the same prescription → works. Verified end-to-end: video title and.en.vttauto-subtitles download successfully.Re-run the documented install command with
-c constraints.txt→ pip downgrades yt-dlp back to 2025.5.22 → broken again.Expected vs actual
no such option: --js-runtimes), and the pin itself can no longer parse 2026 YouTube (YoutubeIEContentProviderLogger.debug() ... 'once').Minor related observation:
doctorcan show YouTube as ✅ while extraction is actually broken, because the probe isyt-dlp --version, which succeeds even with an invalid config option or a stale extractor.Root cause (v1.5.0 tag sources)
constraints.txt:11→yt-dlp==2025.5.22agent_reach/channels/youtube.py:57-64→ when Node is the JS runtime, doctor warns and prints the fix commandagent_reach/utils/paths.py:29-46(render_ytdlp_fix_command) → renders the--js-runtimes nodeconfig append--js-runtimesonly exists in newer yt-dlp releases (present in 2026.7.4; rejected by 2025.5.22), so v1.5.0 prescribes a flag its own tested pin cannot parse. Independently, yt-dlp is a rolling extractor — a ~14-month-old pin cannot track YouTube's changes.Suggested fix
constraints.txtyt-dlp pin to a current release (≥ 2026.x), and ideally add a CI smoke test that runs the pinned yt-dlp against a live YouTube URL so a dead pin is caught automatically; or--js-runtimesprescription on the detected yt-dlp version (only prescribe when the flag is supported), and have doctor warn when the installed yt-dlp is significantly stale.-c constraints.txtwill downgrade a user-upgraded yt-dlp (easy footgun after a manual fix).Related: #378 mentions the stale yt-dlp pin in passing (security/staleness angle); this issue is the concrete functional break plus the self-contradicting doctor prescription.