nodejs/node · error · ValueError

Every filter in --filters must start with + or - ({filt} doe

Error message

Every filter in --filters must start with + or - ({filt} does not)

What it means

Raised by the --filters parser in Node's tools/cpplint.py (a vendored cpplint clone): after expanding shortcuts and collecting filters, it validates that every filter starts with '+' (enable) or '-' (disable). Any filter lacking that sign prefix is a syntax error.

Source

Thrown at tools/cpplint.py:1509

        # Default filters always have less priority than the flag ones.
        self.filters = _DEFAULT_FILTERS[:]
        self.AddFilters(filters)

    def AddFilters(self, filters):
        """Adds more filters to the existing list of error-message filters."""
        for filt in filters.split(","):
            clean_filt = filt.strip()
            if clean_filt:
                if len(clean_filt) > 1 and clean_filt[1:] in _FILTER_SHORTCUTS:
                    starting_char = clean_filt[0]
                    new_filters = [starting_char + x for x in _FILTER_SHORTCUTS[clean_filt[1:]]]
                    self.filters.extend(new_filters)
                else:
                    self.filters.append(clean_filt)
        for filt in self.filters:
            if not filt.startswith(("+", "-")):
                msg = f"Every filter in --filters must start with + or - ({filt} does not)"
                raise ValueError(msg)

    def BackupFilters(self):
        """Saves the current filter list to backup storage."""
        self._filters_backup = self.filters[:]

    def RestoreFilters(self):
        """Restores filters previously backed up."""
        self.filters = self._filters_backup[:]

    def ResetErrorCounts(self):
        """Sets the module's error statistic back to zero."""
        self.error_count = 0
        self.errors_by_category = {}

    def IncrementErrorCount(self, category):
        """Bumps the module's error statistic."""
        self.error_count += 1
        if self.counting in ("toplevel", "detailed"):

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Prefix every filter with + or - : use --filters=+readability/runtime,-build/namespaces.
  2. Use the registered shortcuts (e.g. +readability) which expand to signed sub-filters, ensuring consistency.
  3. Validate the filter string in your CI script before invoking cpplint.

Example fix

# before
--filters=readability/runtime,build/namespaces
# after
--filters=+readability/runtime,-build/namespaces
Defensive patterns

Strategy: validation

Validate before calling

def validate_cpplint_filters(filters: str) -> None:
    for filt in filters.split(','):
        f = filt.strip()
        if f and not f.startswith(('+', '-')):
            raise ValueError(f'Filter {f!r} must start with + or -')

Type guard

def are_valid_filters(filters: str) -> bool:
    return all(not f.strip() or f.strip().startswith(('+','-')) for f in filters.split(','))

Try / catch

null

Prevention

When it happens

Trigger: Passing --filters=readability/runtime,build/namespaces (missing the leading +/- on each token), or a filter shortcut expansion that produced a sign-less entry, or whitespace-only entries after splitting on commas.

Common situations: Copy-pasting a cpplint filter list from a guide that omits the +/- convention; migrating from a different linter whose filter syntax is bare category names; a CI config that builds the --filters string dynamically and forgets the sign.

Related errors


AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13). Data as JSON: /api/errors/da81f2cf387ba40e. Report an issue: GitHub.