pypa/pip · error · ClassNotFound

no lexer for filename {fn!r} found

Error message

no lexer for filename {fn!r} found

What it means

Raised by guess_lexer_for_filename when no lexer's filename glob (in filenames or alias_filenames) matches the basename, so there are zero candidate lexers to score with analyse_text. Distinct from get_lexer_for_filename because it also checks alias_filenames.

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 d7d0d0a394)

Solutions

  1. Use guess_lexer(text) for pure content-based detection (ignores filename).
  2. Use get_lexer_by_name with an explicit alias.
  3. Register a plugin lexer covering the extension.

Example fix

# before
lex = guess_lexer_for_filename('file.xyz', text)
# after
lex = guess_lexer(text)
Defensive patterns

Strategy: fallback

Validate before calling

from pygments.lexers import guess_lexer_for_filename, guess_lexer, TextLexer
from pygments.util import ClassNotFound
def guess_lex(fn, text):
    try:
        return guess_lexer_for_filename(fn, text)
    except ClassNotFound:
        try:
            return guess_lexer(text)
        except ClassNotFound:
            return TextLexer()

Try / catch

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

Prevention

When it happens

Trigger: guess_lexer_for_filename('archive.xyz', text) where no lexer pattern covers .xyz.

Common situations: Editor/preview tool guessing a lexer from an unknown extension; custom build artifact extension; extension removed from a plugin.

Related errors


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