Skip to content

Stop concurrent downloads corrupting the shared cookies.txt - #577

Merged
henriquesebastiao merged 1 commit into
henriquesebastiao:mainfrom
chiliec:fix/cookies-concurrent-writeback
Nov 13, 2026
Merged

henriquesebastiao merged 1 commit into
henriquesebastiao:mainfrom
chiliec:fix/cookies-concurrent-writeback

Conversation

@chiliec

@chiliec chiliec commented Nov 12, 2026

Copy link
Copy Markdown
Contributor

yt-dlp rewrites cookiefile when the YoutubeDL context closes (it truncates the file and writes the jar back). When a playlist runs several downloads in parallel they all point at the same /data/cookies.txt, so one instance truncates it while another is reading it — which is the intermittent "does not look like a Netscape format cookies file" from #570. Retrying works because by then the write has finished.

This gives each download a private copy of the cookie jar, so yt-dlp's save-back lands on a throwaway temp file and the shared one is never the file being rewritten.

Fixes #570.

Tested with a yt-dlp fake that rewrites cookiefile on exit: without the change the shared cookies.txt is clobbered, with it the file stays byte-for-byte unchanged. Full downloader + cookies suites pass (pytest tests/test_downloader_extended.py tests/test_cookies_store.py tests/test_downloader.py, 144 passed), ruff clean.

yt-dlp rewrites cookiefile when it closes, so several downloads from one
playlist kept truncating the single cookies.txt at once and a concurrent
reader hit a half-written file ("does not look like a Netscape format
cookies file"). Give each download a private copy of the jar so the
save-back never touches the shared path.

Fixes henriquesebastiao#570. Tested with a yt-dlp fake that rewrites cookiefile on exit;
the shared file is now left byte-for-byte unchanged.
@github-actions

Copy link
Copy Markdown

👋 Welcome to Downtify, and thanks for your first pull request!

It's great to have you here. Every contribution (code, tests, docs or translations) helps keep Downtify alive, and we're glad you chose to spend your time on it. A maintainer will review this PR as soon as possible. In the meantime, here's what helps it get merged
quickly.

✅ Before review

  • Read CONTRIBUTING.md: local setup, coding standards and the full PR checklist.
  • Rebase on the latest main so the diff only contains your change.
  • Format and lint: run make format, then make lint (Ruff for Python, Prettier for the frontend and docs). CI runs the same checks.
  • Run the tests: make test (pytest + Vitest). New behavior should come with a test, or the description should explain why it can't.
  • Update the docs if the change is user-facing (a new setting, env var, endpoint or UI control): a short note in README.md and the details in docs/.
🧭 Project rules worth knowing
  • Tests run offline. Stub HTTP with fixtures or monkeypatch. Never call Spotify, YouTube or lrclib from a test.
  • The API is a contract. The web app and the Android client depend on the current endpoint paths and response shapes. Add new endpoints or fields instead of renaming or removing existing ones.
  • No Spotify credentials. spotdl, spotipy and the Spotify Web API were removed on purpose. Metadata comes from the public embed endpoints.
  • Don't hand-edit requirements.txt. Change pyproject.toml, then run uv lock && make export.
  • Don't silence the linter with # noqa or wider ignore rules. Fix the code instead.
  • UI text goes in the locale files (frontend/src/i18n/locales/en.js), never hard-coded in components.
  • Don't bump the version. The maintainer does that at release time.

📝 A good PR description

  • What changed and why, plus Closes #123 if it fixes an issue.
  • Screenshots or a short clip for UI changes.
  • How you tested it: what you ran, and for changes to downloading, the track and playlist you pulled to check tags, cover art and lyrics.

💬 Need help?

  • Questions about the code or the direction of a change: ask right here, or open a thread in Discussions.
  • Bigger changes go more smoothly when they start as an issue, so we can agree on the scope first.
  • Want to translate the app or the documentation? See Internationalization.
  • Found a security issue? Please don't post it publicly. Email contato@henriquesebastiao.com instead.

Reviews are a conversation, so expect a round or two of feedback. That's normal, not a sign something is wrong. By contributing, you agree that your work is licensed under the project's AGPL-3.0
license.

Thanks again, and welcome aboard! 🎶

@chiliec

chiliec commented Nov 12, 2026

Copy link
Copy Markdown
Contributor Author

The failing prettier check isn't from this PR's diff — it's Python only, which prettier doesn't process (the check logs Prettier result: 0). The creyD/prettier_action step reformatted 2 unrelated frontend/docs files and then failed trying to auto-commit them back with fatal: You are not currently on a branch, which that action hits on fork PRs. All other checks (Tests, Frontend tests, label) are green. Locally: pytest tests/test_downloader_extended.py tests/test_cookies_store.py tests/test_downloader.py → 144 passed, and ruff check/format clean.

@henriquesebastiao
henriquesebastiao merged commit d755cd5 into henriquesebastiao:main Nov 13, 2026
6 of 7 checks passed
@github-project-automation github-project-automation Bot moved this to Done in Downtify Nov 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Random "ERROR: '/data/cookies.txt' does not look like a Netscape format cookies file"

2 participants