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

  1. Base the child environment on the parent: env = {**os.environ, 'MYVAR': 'x'} instead of a fresh dict
  2. Explicitly set ComSpec (e.g. C:\Windows\System32\cmd.exe) or at least SystemRoot when you must strip the environment
  3. Verify in the parent process: os.environ.get('ComSpec') or os.environ.get('SystemRoot') before spawning
  4. 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

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


AI-assisted analysis of yt-dlp/yt-dlp@81ecd58b13 (2026-08-22). Data as JSON: /api/errors/59a230ef04682de3. Report an issue: GitHub.