pypa/pip · error · TypeError

lex() argument must be a lexer instance, not a class

Error message

lex() argument must be a lexer instance, not a class

What it means

Raised by pygments.lex() when the lexer argument is a RegexLexer *subclass* (a class) rather than an *instance*. lex() tries lexer.get_tokens(code); if that raises TypeError, it checks whether the argument is a class that subclasses RegexLexer and re-raises this clearer message. This is a usability guard against a very common mistake.

Solutions

  1. Instantiate the lexer class before passing it: lex(code, PythonLexer()).
  2. Use get_lexer_by_name('python') which returns an already-instantiated lexer.
  3. Use the top-level highlight(code, lexer_instance, formatter_instance) helper and ensure all three are instances.

Example fix

# before
from pip._vendor.pygments.lexers import PythonLexer
tokens = pygments.lex(code, PythonLexer)
# after
tokens = pygments.lex(code, PythonLexer())
Defensive patterns

Strategy: type-guard

Validate before calling

from inspect import isclass
if isclass(lexer):
    raise TypeError('pass a lexer instance, not the class')

Type guard

def is_lexer_instance(obj) -> bool:
    from pip._vendor.pygments.lexer import Lexer
    return isinstance(obj, Lexer)

Try / catch

try:
    tokens = pygments.lex(code, lexer)
except TypeError as e:
    if 'lexer instance' in str(e):
        lexer = lexer()
        tokens = pygments.lex(code, lexer)
    else:
        raise

Prevention

When it happens

Trigger: Calling pygments.lex(code, PythonLexer) (passing the class) instead of pygments.lex(code, PythonLexer()). The TypeError from calling an unbound method triggers the heuristic at __init__.py:43-49.

Common situations: Following an example that forgot to instantiate; copy-paste from docs showing the class name; refactoring from get_lexer_by_name (returns instance) to a direct class reference.

Related errors


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

Appendix: source

Thrown at src/pip/_vendor/pygments/__init__.py:47

__version__ = '2.20.0'
__docformat__ = 'restructuredtext'

__all__ = ['lex', 'format', 'highlight']


def lex(code, lexer):
    """
    Lex `code` with the `lexer` (must be a `Lexer` instance)
    and return an iterable of tokens. Currently, this only calls
    `lexer.get_tokens()`.
    """
    try:
        return lexer.get_tokens(code)
    except TypeError:
        # Heuristic to catch a common mistake.
        from pip._vendor.pygments.lexer import RegexLexer
        if isinstance(lexer, type) and issubclass(lexer, RegexLexer):
            raise TypeError('lex() argument must be a lexer instance, '
                            'not a class')
        raise


def format(tokens, formatter, outfile=None):  # pylint: disable=redefined-builtin
    """
    Format ``tokens`` (an iterable of tokens) with the formatter ``formatter``
    (a `Formatter` instance).

    If ``outfile`` is given and a valid file object (an object with a
    ``write`` method), the result will be written to it, otherwise it
    is returned as a string.
    """
    try:
        if not outfile:
            realoutfile = getattr(formatter, 'encoding', None) and BytesIO() or StringIO()
            formatter.format(tokens, realoutfile)
            return realoutfile.getvalue()

View on GitHub (pinned to f399c37189)