pypa/pip · error · ClassNotFound

cannot read {filename}: {err}

Error message

cannot read {filename}: {err}

What it means

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.

Source

Thrown at src/pip/_vendor/pygments/formatters/__init__.py:111

    :exc:`pygments.util.ClassNotFound` is raised if there are any errors loading
    the formatter.

    .. versionadded:: 2.2
    """
    try:
        # This empty dict will contain the namespace for the exec'd file
        custom_namespace = {}
        with open(filename, 'rb') as f:
            exec(f.read(), custom_namespace)
        # Retrieve the class `formattername` from that namespace
        if formattername not in custom_namespace:
            raise ClassNotFound(f'no valid {formattername} class found in {filename}')
        formatter_class = custom_namespace[formattername]
        # And finally instantiate it with the options
        return formatter_class(**options)
    except OSError as err:
        raise ClassNotFound(f'cannot read {filename}: {err}')
    except ClassNotFound:
        raise
    except Exception as err:
        raise ClassNotFound(f'error when loading custom formatter: {err}')


def get_formatter_for_filename(fn, **options):
    """
    Return a :class:`.Formatter` subclass instance that has a filename pattern
    matching `fn`. The formatter is given the `options` at its instantiation.

    Will raise :exc:`pygments.util.ClassNotFound` if no formatter for that filename
    is found.
    """
    fn = basename(fn)
    for modname, name, _, filenames, _ in FORMATTERS.values():
        for filename in filenames:
            if _fn_matches(fn, filename):

View on GitHub (pinned to d7d0d0a394)

Solutions

  1. Verify the path with os.path.exists/os.path.isfile before calling.
  2. Use an absolute path constructed from a known base directory.
  3. Fix filesystem permissions or correct the path.

Example fix

# before
load_formatter_from_file('fmts/myfmt.py')  # wrong cwd
# after
import os
base = os.path.dirname(os.path.abspath(__file__))
load_formatter_from_file(os.path.join(base, 'fmts', 'myfmt.py'))
Defensive patterns

Strategy: validation

Validate before calling

import os
def readable_file(p):
    return os.path.isfile(p) and os.access(p, os.R_OK)
# before calling:
if not readable_file(filename):
    raise FileNotFoundError(filename)

Try / catch

from pygments.util import ClassNotFound
try:
    fmt = load_formatter_from_file(fn)
except ClassNotFound as e:
    if 'cannot read' in str(e):
        fmt = get_formatter_by_name('html')  # fallback
    else:
        raise

Prevention

When it happens

Trigger: load_formatter_from_file('missing.py'), passing a directory path, or running from a different cwd so a relative path no longer resolves.

Common situations: 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.

Related errors


AI-assisted analysis of pypa/pip@d7d0d0a394 (2026-08-04). Data as JSON: /data/errors/6c1c96a1e4bc7563.json. Report an issue: GitHub.