pypa/pip · error · ClassNotFound

no lexer for filename

Error message

no lexer for filename {fn!r} found

What it means

Raised by guess_lexer_for_filename() as a ClassNotFound when the set matching_lexers is empty (line 281-282): no lexer class returned by _iter_lexerclasses() has a filenames or alias_filenames glob matching basename(fn). Unlike get_lexer_for_filename it also feeds text to analyse_text, but it short-circuits before that if no filename pattern matches at all.

Solutions

  1. Fall back to guess_lexer(text) which ignores the filename and scores purely on content analyse_text().
  2. Pre-register a filename glob for the extension via a custom plugin lexer entry point.
  3. Normalize/normalize the filename (strip query strings, lower-case the extension) before passing it.

Example fix

// before
lexer = guess_lexer_for_filename('snippet.unknownext', text)

// after
from pygments.lexers import guess_lexer_for_filename, guess_lexer
try:
    lexer = guess_lexer_for_filename('snippet.unknownext', text)
except ClassNotFound:
    lexer = guess_lexer(text)
Defensive patterns

Strategy: fallback

Validate before calling

from pygments.lexers import _iter_lexerclasses
from os.path import basename
import fnmatch
def filename_has_match(fn):
    b = basename(fn)
    return any(fnmatch.fnmatch(b, pat) for lx in _iter_lexerclasses() for pat in lx.filenames)

Try / catch

from pygments.lexers import guess_lexer_for_filename, guess_lexer
from pygments.util import ClassNotFound
try:
    lexer = guess_lexer_for_filename(fn, text)
except ClassNotFound:
    lexer = guess_lexer(text)

Prevention

When it happens

Trigger: Calling guess_lexer_for_filename('data.unknown', text) where no lexer declares a glob for '*.unknown'; the filename has no extension; the filename's extension is registered only as an alias_filename in a plugin that is not installed.

Common situations: Processing user-uploaded files with arbitrary or missing extensions; relying on filename matching for a language that only identifies itself by content (no extension convention); vendored Pygments missing a plugin that a standalone Pygments install would provide.

Related errors


AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08). Data as JSON: /api/errors/b13b0f02c775d7b6. Report an issue: GitHub.

Appendix: source

Thrown at src/pip/_vendor/pygments/lexers/__init__.py:282

    or `alias_filenames` that matches `filename` are taken into consideration.

    :exc:`pygments.util.ClassNotFound` is raised if no lexer thinks it can
    handle the content.
    """
    fn = basename(_fn)
    primary = {}
    matching_lexers = set()
    for lexer in _iter_lexerclasses():
        for filename in lexer.filenames:
            if _fn_matches(fn, filename):
                matching_lexers.add(lexer)
                primary[lexer] = True
        for filename in lexer.alias_filenames:
            if _fn_matches(fn, filename):
                matching_lexers.add(lexer)
                primary[lexer] = False
    if not matching_lexers:
        raise ClassNotFound(f'no lexer for filename {fn!r} found')
    if len(matching_lexers) == 1:
        return matching_lexers.pop()(**options)
    result = []
    for lexer in matching_lexers:
        rv = lexer.analyse_text(_text)
        if rv == 1.0:
            return lexer(**options)
        result.append((rv, lexer))

    def type_sort(t):
        # sort by:
        # - analyse score
        # - is primary filename pattern?
        # - priority
        # - last resort: class name
        return (t[0], primary[t[1]], t[1].priority, t[1].__name__)
    result.sort(key=type_sort)

View on GitHub (pinned to f399c37189)