{"record":{"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/f399c3718970b1b0e2478dac5296eb62679a9b86/src/pip/_vendor/pygments/lexers/__init__.py#L139-L175","documentation":"Raised by load_lexer_from_file() as a ClassNotFound when the file was successfully read and exec'd, but the expected class name (lexername, defaulting to \"CustomLexer\") is not present in the resulting namespace (line 156-157). It means the file loaded as valid Python but does not define the class you told Pygments to look for.","triggerScenarios":"Calling load_lexer_from_file('mylexer.py') on a file that defines a class named something other than \"CustomLexer\" (the default lexername), or calling load_lexer_from_file('mylexer.py', lexername='MyLexer') when the file actually defines a differently-named class. The exec() at line 154 succeeds, but the check `if lexername not in custom_namespace` at line 156 fails.","commonSituations":"Forgetting to pass the explicit lexername argument when your custom lexer class is not named CustomLexer; refactoring/renaming the lexer class but not the call site; loading a file that defines the class conditionally (e.g., inside an if-block that evaluates false) so it never lands in the top-level namespace.","solutions":["Check the class name defined in your file and pass it explicitly: load_lexer_from_file('mylexer.py', lexername='YourActualClassName').","Ensure the lexer class is defined at module top level (not nested inside a function, conditional, or try/except that swallows it).","Verify the filename argument resolves relative to the current working directory, since load_lexer_from_file resolves it via open(filename) without a search path."],"exampleFix":"// before\nload_lexer_from_file('mylexer.py')  # file defines class MyLangLexer\n\n// after\nload_lexer_from_file('mylexer.py', lexername='MyLangLexer')","handlingStrategy":"validation","validationCode":"import os, ast\ndef can_load_lexer(filename, lexername='CustomLexer'):\n    if not os.path.isfile(filename):\n        return False, 'file not found'\n    try:\n        tree = ast.parse(open(filename, 'rb').read(), filename=filename)\n    except SyntaxError as e:\n        return False, f'syntax error: {e}'\n    names = {n.name for n in ast.walk(tree) if isinstance(n, ast.ClassDef)}\n    if lexername not in names:\n        return False, f'{lexername} not defined; found {sorted(names)}'\n    return True, 'ok'","typeGuard":"def is_valid_lexer_class(cls) -> bool:\n    from pygments.lexer import Lexer\n    return isinstance(cls, type) and issubclass(cls, Lexer)","tryCatchPattern":"from pygments.util import ClassNotFound\ntry:\n    lexer = load_lexer_from_file(path, lexername=name)\nexcept ClassNotFound as e:\n    logger.warning('lexer load failed: %s', e)\n    lexer = get_lexer_by_name('text')","preventionTips":["Always pass the explicit lexername matching the class defined in the file rather than relying on the CustomLexer default.","AST-inspect the file for top-level ClassDef names before calling load_lexer_from_file."],"tags":["pygments","lexer","custom-lexer","class-not-found"],"backgroundTag":null,"analyzedSha":"f399c3718970b1b0e2478dac5296eb62679a9b86","analyzedAt":"2026-08-08T23:01:42.227Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}