{"record":{"id":"59a230ef04682de3","repo":"yt-dlp/yt-dlp","slug":"invalid-value-r-in-format-specification-r","errorCode":null,"errorMessage":"Invalid value {!r} in format specification {!r}","messagePattern":"Invalid value (.+?) in format specification (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"yt_dlp/YoutubeDL.py","lineNumber":2229,"sourceCode":"            '>=': operator.ge,\n            '=': operator.eq,\n            '!=': operator.ne,\n        }\n        operator_rex = re.compile(r'''(?x)\\s*\n            (?P<key>[\\w.-]+)\\s*\n            (?P<op>{})(?P<none_inclusive>\\s*\\?)?\\s*\n            (?P<value>[0-9.]+(?:[kKmMgGtTpPeEzZyY]i?[Bb]?)?)\\s*\n            '''.format('|'.join(map(re.escape, OPERATORS.keys()))))\n        m = operator_rex.fullmatch(filter_spec)\n        if m:\n            try:\n                comparison_value = float(m.group('value'))\n            except ValueError:\n                comparison_value = parse_filesize(m.group('value'))\n                if comparison_value is None:\n                    comparison_value = parse_filesize(m.group('value') + 'B')\n                if comparison_value is None:\n                    raise ValueError(\n                        'Invalid value {!r} in format specification {!r}'.format(\n                            m.group('value'), filter_spec))\n            op = OPERATORS[m.group('op')]\n\n        if not m:\n            STR_OPERATORS = {\n                '=': operator.eq,\n                '^=': lambda attr, value: attr.startswith(value),\n                '$=': lambda attr, value: attr.endswith(value),\n                '*=': lambda attr, value: value in attr,\n                '~=': lambda attr, value: value.search(attr) is not None,\n            }\n            str_operator_rex = re.compile(r'''(?x)\\s*\n                (?P<key>[a-zA-Z0-9._-]+)\\s*\n                (?P<negation>!\\s*)?(?P<op>{})\\s*(?P<none_inclusive>\\?\\s*)?\n                (?P<quote>[\"'])?\n                (?P<value>(?(quote)(?:(?!(?P=quote))[^\\\\]|\\\\.)+|[\\w.-]+))\n                (?(quote)(?P=quote))\\s*","sourceCodeStart":2211,"sourceCodeEnd":2247,"githubUrl":"https://github.com/yt-dlp/yt-dlp/blob/81ecd58b1394793e6da9998cc19fdb45657f1685/yt_dlp/YoutubeDL.py#L2211-L2247","documentation":"On Windows, yt_dlp's Popen wrapper builds the cmd.exe command line via __comspec(): it takes %ComSpec%, or falls back to %SystemRoot%\\System32\\cmd.exe. If the resulting path is not absolute (ComSpec unset or relative AND SystemRoot unset) it raises FileNotFoundError('shell not found: neither %ComSpec% nor %SystemRoot% is set'). The environment handed to the process is missing the standard Windows shell variables.","triggerScenarios":"Spawning yt-dlp subprocesses with a hand-built minimal env dict instead of inheriting os.environ; running under stripped environments (Windows service, scheduled task with cleared env, WinPE, some CI/container images); code that deletes ComSpec/SystemRoot while sanitizing the environment.","commonSituations":"Scripts building env from scratch ({'PATH': ...}) when calling yt-dlp's downloader on Windows; sandboxed test runs scrubbing os.environ; minimal Windows containers lacking the default variables.","solutions":["Base the child environment on the parent: env = {**os.environ, 'MYVAR': 'x'} instead of a fresh dict","Explicitly set ComSpec (e.g. C:\\Windows\\System32\\cmd.exe) or at least SystemRoot when you must strip the environment","Verify in the parent process: os.environ.get('ComSpec') or os.environ.get('SystemRoot') before spawning","If you cannot fix the env, avoid code paths that need cmd.exe quoting (do not pass Windows-specific newline-escape shell args)"],"exampleFix":"# before\nsubprocess.run(cmd, env={'PATH': r'C:\\Windows\\System32'})\n# after\nsubprocess.run(cmd, env={**os.environ, 'PATH': r'C:\\Windows\\System32'})","handlingStrategy":"validation","validationCode":"import os\n\nWINDOWS_SHELL_VARS = ('ComSpec', 'SystemRoot')\n\nif os.name == 'nt' and not any(os.environ.get(v) for v in WINDOWS_SHELL_VARS):\n    os.environ['ComSpec'] = r'C:\\Windows\\System32\\cmd.exe'   # or abort with a clear message","typeGuard":null,"tryCatchPattern":"import os\nfrom yt_dlp.utils import Popen  # Windows wrapper that resolves %ComSpec%\n\ntry:\n    proc = Popen(args, ...)\nexcept FileNotFoundError as e:\n    if 'ComSpec' in str(e):\n        os.environ['SystemRoot'] = os.environ.get('SystemRoot', r'C:\\Windows')\n        proc = Popen(args, ...)\n    else:\n        raise","preventionTips":["Always derive child environments from os.environ ({**os.environ, ...}) rather than fresh dicts on Windows","In services/scheduled tasks/containers, explicitly set ComSpec or SystemRoot in the job definition","Assert the required Windows shell variables exist in smoke tests of minimal-environment deployments"],"tags":["windows","subprocess","environment-variables","comspec","yt-dlp"],"backgroundTag":"missing-env-var","analyzedSha":"81ecd58b1394793e6da9998cc19fdb45657f1685","analyzedAt":"2026-08-22T12:21:25.439Z","schemaVersion":2},"datasetVersion":"2026-08-22T14:17:55.899Z"}