{"id":"44ac1b7e89ae5b7b","repo":"pypa/pip","slug":"no-valid-lexername-class-found-in-filename","errorCode":null,"errorMessage":"no valid {lexername} class found in {filename}","messagePattern":"no valid (.+?) class found in (.+?)","errorType":"exception","errorClass":"ClassNotFound","httpStatus":null,"severity":"error","filePath":"src/pip/_vendor/pygments/lexers/__init__.py","lineNumber":157,"sourceCode":"    directory, which contains a Lexer class. By default, it expects the\n    Lexer to be name CustomLexer; you can specify your own class name\n    as the second argument to this function.\n\n    Users should be very careful with the input, because this method\n    is equivalent to running eval on the input file.\n\n    Raises ClassNotFound if there are any problems importing the Lexer.\n\n    .. versionadded:: 2.2\n    \"\"\"\n    try:\n        # This empty dict will contain the namespace for the exec'd file\n        custom_namespace = {}\n        with open(filename, 'rb') as f:\n            exec(f.read(), custom_namespace)\n        # Retrieve the class `lexername` from that namespace\n        if lexername not in custom_namespace:\n            raise ClassNotFound(f'no valid {lexername} class found in {filename}')\n        lexer_class = custom_namespace[lexername]\n        # And finally instantiate it with the options\n        return lexer_class(**options)\n    except OSError as err:\n        raise ClassNotFound(f'cannot read {filename}: {err}')\n    except ClassNotFound:\n        raise\n    except Exception as err:\n        raise ClassNotFound(f'error when loading custom lexer: {err}')\n\n\ndef find_lexer_class_for_filename(_fn, code=None):\n    \"\"\"Get a lexer for a filename.\n\n    If multiple lexers match the filename pattern, use ``analyse_text()`` to\n    figure out which one is more appropriate.\n\n    Returns None if not found.","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/pypa/pip/blob/d7d0d0a39494e28ec1c407bd0680e4a4d1067791/src/pip/_vendor/pygments/lexers/__init__.py#L139-L175","documentation":"Raised by load_lexer_from_file when the file was opened and exec'd successfully but the expected class name (lexername, default 'CustomLexer') is not present in the resulting namespace.","triggerScenarios":"load_lexer_from_file('mylex.py', 'MyLexer') where mylex.py defines a class with a different name, nests it, or defines none.","commonSituations":"Forgetting to pass the class name and relying on the default CustomLexer that the file doesn't use; class defined inside a conditional/guard; copy-pasted lexer with its original name.","solutions":["Confirm the exact class name in the file and pass it as lexername.","Name your class CustomLexer to match the default.","Define the class at module top level."],"exampleFix":"# before\nload_lexer_from_file('mylex.py')  # file defines SqlLexer\n# after\nload_lexer_from_file('mylex.py', 'SqlLexer')","handlingStrategy":"validation","validationCode":"import inspect\ndef class_in_file(filename, cls_name):\n    ns = {}\n    with open(filename, 'rb') as f:\n        exec(f.read(), ns)\n    return cls_name in ns and inspect.isclass(ns[cls_name])","typeGuard":null,"tryCatchPattern":"from pygments.util import ClassNotFound\nfrom pygments.lexers import load_lexer_from_file, TextLexer\ntry:\n    lex = load_lexer_from_file(fn, name)\nexcept ClassNotFound:\n    lex = TextLexer()","preventionTips":["Keep the custom lexer class at module scope.","Use the conventional name CustomLexer."],"tags":["pygments","lexer","custom","dynamic-load"],"analyzedSha":"d7d0d0a39494e28ec1c407bd0680e4a4d1067791","analyzedAt":"2026-08-04T20:55:04.259Z","schemaVersion":2}