yt-dlp/yt-dlp · error · ValueError
Invalid value {!r} in format specification {!r}
Error message
Invalid value {!r} in format specification {!r} What it means
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.
Source
Thrown at yt_dlp/YoutubeDL.py:2229
'>=': operator.ge,
'=': operator.eq,
'!=': operator.ne,
}
operator_rex = re.compile(r'''(?x)\s*
(?P<key>[\w.-]+)\s*
(?P<op>{})(?P<none_inclusive>\s*\?)?\s*
(?P<value>[0-9.]+(?:[kKmMgGtTpPeEzZyY]i?[Bb]?)?)\s*
'''.format('|'.join(map(re.escape, OPERATORS.keys()))))
m = operator_rex.fullmatch(filter_spec)
if m:
try:
comparison_value = float(m.group('value'))
except ValueError:
comparison_value = parse_filesize(m.group('value'))
if comparison_value is None:
comparison_value = parse_filesize(m.group('value') + 'B')
if comparison_value is None:
raise ValueError(
'Invalid value {!r} in format specification {!r}'.format(
m.group('value'), filter_spec))
op = OPERATORS[m.group('op')]
if not m:
STR_OPERATORS = {
'=': operator.eq,
'^=': lambda attr, value: attr.startswith(value),
'$=': lambda attr, value: attr.endswith(value),
'*=': lambda attr, value: value in attr,
'~=': lambda attr, value: value.search(attr) is not None,
}
str_operator_rex = re.compile(r'''(?x)\s*
(?P<key>[a-zA-Z0-9._-]+)\s*
(?P<negation>!\s*)?(?P<op>{})\s*(?P<none_inclusive>\?\s*)?
(?P<quote>["'])?
(?P<value>(?(quote)(?:(?!(?P=quote))[^\\]|\\.)+|[\w.-]+))
(?(quote)(?P=quote))\s*View on GitHub (pinned to 81ecd58b13)
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)
Example fix
# before
subprocess.run(cmd, env={'PATH': r'C:\Windows\System32'})
# after
subprocess.run(cmd, env={**os.environ, 'PATH': r'C:\Windows\System32'}) Defensive patterns
Strategy: validation
Validate before calling
import os
WINDOWS_SHELL_VARS = ('ComSpec', 'SystemRoot')
if os.name == 'nt' and not any(os.environ.get(v) for v in WINDOWS_SHELL_VARS):
os.environ['ComSpec'] = r'C:\Windows\System32\cmd.exe' # or abort with a clear message Try / catch
import os
from yt_dlp.utils import Popen # Windows wrapper that resolves %ComSpec%
try:
proc = Popen(args, ...)
except FileNotFoundError as e:
if 'ComSpec' in str(e):
os.environ['SystemRoot'] = os.environ.get('SystemRoot', r'C:\Windows')
proc = Popen(args, ...)
else:
raise Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.
Related errors
- Extractor failed to obtain "id"
- Requested format is not available. Use --list-formats for a
- {note} failed: Unable to run PhantomJS binary
- Impersonate target "{impersonate_target}" is not available.
- Invalid js_runtimes format, expected a dict of {runtime: {co
AI-assisted analysis of yt-dlp/yt-dlp@81ecd58b13 (2026-08-22).
Data as JSON: /api/errors/59a230ef04682de3.
Report an issue: GitHub.