{"record":{"id":"edb313c11300fe55","repo":"ytdl-org/youtube-dl","slug":"playlist-end-must-be-greater-than-playlist-start","errorCode":null,"errorMessage":"Playlist end must be greater than playlist start","messagePattern":"Playlist end must be greater than playlist start","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"youtube_dl/__init__.py","lineNumber":206,"sourceCode":"        return parsed_retries\n    if opts.retries is not None:\n        opts.retries = parse_retries(opts.retries)\n    if opts.fragment_retries is not None:\n        opts.fragment_retries = parse_retries(opts.fragment_retries)\n    if opts.buffersize is not None:\n        numeric_buffersize = FileDownloader.parse_bytes(opts.buffersize)\n        if numeric_buffersize is None:\n            parser.error('invalid buffer size specified')\n        opts.buffersize = numeric_buffersize\n    if opts.http_chunk_size is not None:\n        numeric_chunksize = FileDownloader.parse_bytes(opts.http_chunk_size)\n        if not numeric_chunksize:\n            parser.error('invalid http chunk size specified')\n        opts.http_chunk_size = numeric_chunksize\n    if opts.playliststart <= 0:\n        raise ValueError('Playlist start must be positive')\n    if opts.playlistend not in (-1, None) and opts.playlistend < opts.playliststart:\n        raise ValueError('Playlist end must be greater than playlist start')\n    if opts.extractaudio:\n        if opts.audioformat not in ['best', 'aac', 'flac', 'mp3', 'm4a', 'opus', 'vorbis', 'wav']:\n            parser.error('invalid audio format specified')\n    if opts.audioquality:\n        opts.audioquality = opts.audioquality.strip('k').strip('K')\n        if not opts.audioquality.isdigit():\n            parser.error('invalid audio quality specified')\n    if opts.recodevideo is not None:\n        if opts.recodevideo not in ['mp4', 'flv', 'webm', 'ogg', 'mkv', 'avi']:\n            parser.error('invalid video recode format specified')\n    if opts.convertsubtitles is not None:\n        if opts.convertsubtitles not in ['srt', 'vtt', 'ass', 'lrc']:\n            parser.error('invalid subtitle format specified')\n\n    if opts.date is not None:\n        date = DateRange.day(opts.date)\n    else:\n        date = DateRange(opts.dateafter, opts.datebefore)","sourceCodeStart":188,"sourceCodeEnd":224,"githubUrl":"https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/__init__.py#L188-L224","documentation":"Raised on Windows by youtube-dl's file-locking helper: the Win32 LockFileEx call (via msvcrt.get_osfhandle) failed, and ctypes.FormatError() supplies the OS error text. It occurs while acquiring the lock youtube-dl uses for its .part/download coordination and cache files (locked_file context manager). The %r message is the Windows error string, e.g. a sharing violation or access-denied description.","triggerScenarios":"Two youtube-dl processes downloading to the same output file simultaneously; antivirus/backup software holding the file; the file being open in another program (player, torrent client); insufficient permissions on the directory; locking a file on a network share (SMB) that does not support byte-range locks.","commonSituations":"Cron jobs or launchers that overlap runs; Windows Defender scanning .part files at the exact moment of locking; downloading to a NAS/SMB path where LockFileEx semantics differ; running without write permission to the output directory.","solutions":["Ensure only one youtube-dl instance writes the same output file at a time (distinct --output templates per job, or a queue).","Read the embedded FormatError text: 'being used by another process' → find the other holder; 'Access is denied' → fix directory/file permissions.","Add the download directory to antivirus exclusions (or accept the race) and retry.","For network shares, download to a local temp dir and move afterwards — LockFileEx over SMB is unreliable."],"exampleFix":"# before\nwith locked_file('video.mp4.part', 'a') as f:  # may fail if locked elsewhere\n    ...\n\n# after\nimport random, time\nfor attempt in range(3):\n    try:\n        with locked_file('video.mp4.part', 'a') as f:\n            ...\n        break\n    except OSError:\n        time.sleep(2 ** attempt + random.random())","handlingStrategy":"retry","validationCode":"import os\n\ndef can_lock(path):\n    d = os.path.dirname(os.path.abspath(path)) or '.'\n    return os.access(d, os.W_OK) and os.path.exists(d)","typeGuard":null,"tryCatchPattern":"from youtube_dl.utils import locked_file\nimport time, random\nfor attempt in range(3):\n    try:\n        with locked_file(path, 'a') as f:\n            f.write(b'')\n        break\n    except OSError as e:\n        if 'Locking file failed' in str(e) and attempt < 2:\n            time.sleep((2 ** attempt) + random.random())\n            continue\n        raise  # persistent holder (AV, other process) — surface it","preventionTips":["Ensure a single writer per output file: unique --output templates per concurrent job.","Add download directories to antivirus/sync exclusions to avoid external holders of .part files.","Avoid locking files on SMB shares; download locally and copy afterwards."],"tags":["windows","file-locking","concurrency","filesystem"],"backgroundTag":null,"analyzedSha":"956b8c585591b401a543e409accb163eeaaa1193","analyzedAt":"2026-08-14T18:59:47.863Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}