ytdl-org/youtube-dl · error · ValueError
Invalid filter part %r
Error message
Invalid filter part %r
What it means
Raised by _match_one() in youtube_dl.utils when a single --match-filter part matches neither the binary comparison grammar (<key><op><value>, =/!=/</<=/>/>=/~= with an int, filesize, or quoted/bare string) nor the unary grammar (key or !key). It is the catch-all syntax error for the filter mini-language; match_str() splits on '&' and evaluates each part with _match_one, so one malformed part fails the whole filter.
Source
Thrown at youtube_dl/utils.py:4933
if actual_value is None:
return m.group('none_inclusive')
return op(actual_value, comparison_value)
UNARY_OPERATORS = {
'': lambda v: (v is True) if isinstance(v, bool) else (v is not None),
'!': lambda v: (v is False) if isinstance(v, bool) else (v is None),
}
operator_rex = re.compile(r'''(?x)\s*
(?P<op>%s)\s*(?P<key>[a-z_]+)
\s*$
''' % '|'.join(map(re.escape, UNARY_OPERATORS.keys())))
m = operator_rex.search(filter_part)
if m:
op = UNARY_OPERATORS[m.group('op')]
actual_value = dct.get(m.group('key'))
return op(actual_value)
raise ValueError('Invalid filter part %r' % filter_part)
def match_str(filter_str, dct):
""" Filter a dictionary with a simple string syntax. Returns True (=passes filter) or false """
return all(
_match_one(filter_part, dct) for filter_part in filter_str.split('&'))
def match_filter_func(filter_str):
def _match_func(info_dict):
if match_str(filter_str, info_dict):
return None
else:
video_title = info_dict.get('title', info_dict.get('id', 'video'))
return '%s does not pass filter %s, skipping ..' % (video_title, filter_str)
return _match_func
View on GitHub (pinned to 956b8c5855)
Solutions
- Rewrite the part as <key><op><value> (e.g. view_count>1000, ext=mp4, !is_live).
- Use only '&' to combine parts; '&&' produces an empty part and triggers this error.
- Check the key is lowercase letters/underscores only and the operator is one of = != < <= > >= ~=.
- Split complex logic across multiple youtube-dl invocations or a wrapper script, since OR/parens are not supported.
Example fix
# before youtube-dl --match-filter "ext==mp4 && view_count>1000" URL # '==' and '&&' are invalid → Invalid filter part # after youtube-dl --match-filter "ext=mp4&view_count>1000" URL
Defensive patterns
Strategy: validation
Validate before calling
import re
BINARY = re.compile(r'^[a-z_]+\s*(=|!=|<|<=|>|>=|~=)\s*.+$')
UNARY = re.compile(r'^!?[a-z_]+$')
def validate_match_filter(filter_str):
for part in filter_str.split('&'):
p = part.strip()
if not p or not (BINARY.match(p) or UNARY.match(p)):
raise ValueError('Invalid filter part %r' % part) Type guard
def is_valid_filter_part(part: str) -> bool:
import re
return bool(re.match(r'^[a-z_]+\s*(=|!=|<|<=|>|>=|~=)\s*.+$', part) or re.match(r'^!?[a-z_]+$', part)) Try / catch
from youtube_dl.utils import match_str
try:
match_str(filter_str, info_dict)
except ValueError as e:
log.warning('skipping malformed filter: %s', e)
accept = True # or fail fast, per policy Prevention
- Combine parts only with single '&', never '&&', ',', or ';'.
- Stick to the grammar key<op>value or !key; there is no OR or parentheses.
- Validate filter strings at startup (regex above) so bad user input fails early.
When it happens
Trigger: Running --match-filter with a part that is empty, contains an unknown key character (keys must be [a-z_]), an unsupported operator (e.g. field==value, field>=), reversed order (100<views), a lone comparison symbol, or separators other than '&' (semicolons and commas are not recognized and end up inside the part).
Common situations: Typos and experimentation with the filter syntax; assuming full boolean expressions (OR, parentheses) exist; using '&&' which yields an empty part after splitting on '&'; copying filter syntax from yt-dlp (which supports more operators) into youtube-dl.
Related errors
- Operator %s does not support string values!
- Invalid integer value %r in filter part %r
- requested format not available
- Giving up retrying
- Invalid URL
AI-assisted analysis of ytdl-org/youtube-dl@956b8c5855 (2026-08-14).
Data as JSON: /api/errors/046d34e50662bc7f.
Report an issue: GitHub.