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
- Fall back to guess_lexer(text) which ignores the filename and scores purely on content analyse_text().
- Pre-register a filename glob for the extension via a custom plugin lexer entry point.
- 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
- Always pair guess_lexer_for_filename with a guess_lexer(text) fallback for unknown extensions.
- Register plugin lexers with filename globs for custom extensions.
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
- no lexer for filename
- no lexer matching the text found
- no lexer for mimetype
- no valid class found in
- cannot read
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)