{"record":{"id":"5c47650158d733b1","repo":"pypa/pip","slug":"cannot-read-filename-err-5c4765","errorCode":null,"errorMessage":"cannot read {filename}: {err}","messagePattern":"cannot read (.+?): (.+?)","errorType":"exception","errorClass":"ClassNotFound","httpStatus":null,"severity":"error","filePath":"src/pip/_vendor/pygments/lexers/__init__.py","lineNumber":162,"sourceCode":"    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.\n    \"\"\"\n    matches = []\n    fn = basename(_fn)\n    for modname, name, _, filenames, _ in LEXERS.values():\n        for filename in filenames:","sourceCodeStart":144,"sourceCodeEnd":180,"githubUrl":"https://github.com/pypa/pip/blob/f399c3718970b1b0e2478dac5296eb62679a9b86/src/pip/_vendor/pygments/lexers/__init__.py#L144-L180","documentation":"Raised by load_lexer_from_file() as a ClassNotFound (wrapping the OSError) when open(filename, 'rb') fails at line 153, caught by the `except OSError as err` branch at line 161-162. It indicates the file path itself could not be opened or read by the OS.","triggerScenarios":"Calling load_lexer_from_file() with a path to a nonexistent file, a directory instead of a file, or a file without read permissions. Any OSError from open() or f.read() lands here.","commonSituations":"Typo or wrong relative path (the function resolves relative to cwd, not sys.path or the package directory); pointing at a directory; file owned by another user with mode 000; path containing the right name but wrong case on case-sensitive filesystems.","solutions":["Verify the file exists with os.path.isfile(filename) before calling, and print os.path.abspath(filename) to confirm the resolved path.","Use an absolute path instead of a relative one, since load_lexer_from_file resolves relative to cwd which may differ from what you expect.","Check filesystem permissions on the target file (read bit must be set for the running user)."],"exampleFix":"// before\nlexer = load_lexer_from_file('custom_lexer.py')\n\n// after\nimport os\npath = os.path.join(os.path.dirname(__file__), 'custom_lexer.py')\nlexer = load_lexer_from_file(path)","handlingStrategy":"validation","validationCode":"import os\ndef path_readable(filename):\n    return os.path.isfile(filename) and os.access(filename, os.R_OK)","typeGuard":null,"tryCatchPattern":"from pygments.util import ClassNotFound\ntry:\n    lexer = load_lexer_from_file(path)\nexcept ClassNotFound as e:\n    if 'cannot read' in str(e):\n        # missing/unreadable file — handle gracefully\n        lexer = None\n    raise","preventionTips":["Resolve the path to absolute before calling and log os.path.abspath to confirm location.","Guard with os.path.isfile() and an os.access(..., os.R_OK) check."],"tags":["pygments","lexer","file-io","custom-lexer"],"backgroundTag":null,"analyzedSha":"f399c3718970b1b0e2478dac5296eb62679a9b86","analyzedAt":"2026-08-08T23:01:42.227Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}