{"id":"6c1c96a1e4bc7563","repo":"pypa/pip","slug":"cannot-read-filename-err","errorCode":null,"errorMessage":"cannot read {filename}: {err}","messagePattern":"cannot read (.+?): (.+?)","errorType":"exception","errorClass":"ClassNotFound","httpStatus":null,"severity":"error","filePath":"src/pip/_vendor/pygments/formatters/__init__.py","lineNumber":111,"sourceCode":"\n    :exc:`pygments.util.ClassNotFound` is raised if there are any errors loading\n    the formatter.\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 `formattername` from that namespace\n        if formattername not in custom_namespace:\n            raise ClassNotFound(f'no valid {formattername} class found in {filename}')\n        formatter_class = custom_namespace[formattername]\n        # And finally instantiate it with the options\n        return formatter_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 formatter: {err}')\n\n\ndef get_formatter_for_filename(fn, **options):\n    \"\"\"\n    Return a :class:`.Formatter` subclass instance that has a filename pattern\n    matching `fn`. The formatter is given the `options` at its instantiation.\n\n    Will raise :exc:`pygments.util.ClassNotFound` if no formatter for that filename\n    is found.\n    \"\"\"\n    fn = basename(fn)\n    for modname, name, _, filenames, _ in FORMATTERS.values():\n        for filename in filenames:\n            if _fn_matches(fn, filename):","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/pypa/pip/blob/d7d0d0a39494e28ec1c407bd0680e4a4d1067791/src/pip/_vendor/pygments/formatters/__init__.py#L93-L129","documentation":"Raised by load_formatter_from_file when open(filename) raises OSError (file not found, permission denied, is a directory, etc.). The path is resolved relative to the current working directory.","triggerScenarios":"load_formatter_from_file('missing.py'), passing a directory path, or running from a different cwd so a relative path no longer resolves.","commonSituations":"Wrong working directory when launching the process; path typos; permission denied on a shared filesystem; passing a path that exists only in a different environment.","solutions":["Verify the path with os.path.exists/os.path.isfile before calling.","Use an absolute path constructed from a known base directory.","Fix filesystem permissions or correct the path."],"exampleFix":"# before\nload_formatter_from_file('fmts/myfmt.py')  # wrong cwd\n# after\nimport os\nbase = os.path.dirname(os.path.abspath(__file__))\nload_formatter_from_file(os.path.join(base, 'fmts', 'myfmt.py'))","handlingStrategy":"validation","validationCode":"import os\ndef readable_file(p):\n    return os.path.isfile(p) and os.access(p, os.R_OK)\n# before calling:\nif not readable_file(filename):\n    raise FileNotFoundError(filename)","typeGuard":null,"tryCatchPattern":"from pygments.util import ClassNotFound\ntry:\n    fmt = load_formatter_from_file(fn)\nexcept ClassNotFound as e:\n    if 'cannot read' in str(e):\n        fmt = get_formatter_by_name('html')  # fallback\n    else:\n        raise","preventionTips":["Prefer absolute paths.","Validate path with os.path.isfile before loading."],"tags":["pygments","formatter","filesystem","custom"],"analyzedSha":"d7d0d0a39494e28ec1c407bd0680e4a4d1067791","analyzedAt":"2026-08-04T20:55:04.259Z","schemaVersion":2}