Skip to content

[Bug]: Config directory location finder doesnt account for the home directory being undetermined. #30449

@Logan-Pageler

Description

@Logan-Pageler

Bug summary

If the home directory cannot be created/written to, matplotlib defaults to creating a temporary folder for its caching/config. However, if the home directory cannot be determined a RunTimeError will be raised.

Code for reproduction

# This will fail on windows
import os
os.environ.pop('HOMEPATH', None)
os.environ.pop('USERPROFILE', None)
import matplotlib

# For linux the following will fail only if the user doesn't exist in the password database
import os
os.environ.pop('HOME', None)
import matplotlib

Actual outcome

You will get the following error:

File ~\Documents\programming\testing\.venv\Lib\site-packages\matplotlib\__init__.py:1010
   1008 rcParams = RcParams()  # The global instance.
   1009 rcParams._update_raw(rcParamsDefault)
-> 1010 rcParams._update_raw(_rc_params_in_file(matplotlib_fname()))
   1011 rcParamsOrig = rcParams.copy()
   1012 with _api.suppress_matplotlib_deprecation_warning():
   1013     # This also checks that all rcParams are indeed listed in the template.
   1014     # Assigning to rcsetup.defaultParams is left only for backcompat.

File ~\Documents\programming\testing\.venv\Lib\site-packages\matplotlib\__init__.py:636, in matplotlib_fname()
    633     yield os.path.join(get_configdir(), 'matplotlibrc')
    634     yield os.path.join(get_data_path(), 'matplotlibrc')
--> 636 for fname in gen_candidates():
    637     if os.path.exists(fname) and not os.path.isdir(fname):
    638         return fname

File ~\Documents\programming\testing\.venv\Lib\site-packages\matplotlib\__init__.py:633, in matplotlib_fname.<locals>.gen_candidates()
    631     yield matplotlibrc
    632     yield os.path.join(matplotlibrc, 'matplotlibrc')
--> 633 yield os.path.join(get_configdir(), 'matplotlibrc')
    634 yield os.path.join(get_data_path(), 'matplotlibrc')

File ~\Documents\programming\testing\.venv\Lib\site-packages\matplotlib\__init__.py:340, in _logged_cached.<locals>.wrapper(**kwargs)
    338 nonlocal called, ret
    339 if not called:
--> 340     ret = func(**kwargs)
    341     called = True
    342     _log.debug(fmt, ret)

File ~\Documents\programming\testing\.venv\Lib\site-packages\matplotlib\__init__.py:579, in get_configdir()
    563 @_logged_cached('CONFIGDIR=%s')
    564 def get_configdir():
    565     """
    566     Return the string path of the configuration directory.
    567 
   (...)    577        directory.
    578     """
--> 579     return _get_config_or_cache_dir(_get_xdg_config_dir)

File ~\Documents\programming\testing\.venv\Lib\site-packages\matplotlib\__init__.py:531, in _get_config_or_cache_dir(xdg_base_getter)
    529     configdir = Path(xdg_base_getter(), "matplotlib")
    530 else:
--> 531     configdir = Path.home() / ".matplotlib"
    532 # Resolve the path to handle potential issues with inaccessible symlinks.
    533 configdir = configdir.resolve()

File ~\AppData\Roaming\uv\python\cpython-3.13.7-windows-x86_64-none\Lib\pathlib\_abc.py:758, in PathBase.home(cls)
    754 @classmethod
    755 def home(cls):
    756     """Return a new path pointing to expanduser('~').
    757     """
--> 758     return cls("~").expanduser()

File ~\AppData\Roaming\uv\python\cpython-3.13.7-windows-x86_64-none\Lib\pathlib\_local.py:808, in Path.expanduser(self)
    806 homedir = os.path.expanduser(self._tail[0])
    807 if homedir[:1] == "~":
--> 808     raise RuntimeError("Could not determine home directory.")
    809 drv, root, tail = self._parse_path(homedir)
    810 return self._from_parsed_parts(drv, root, tail + self._tail[1:])

RuntimeError: Could not determine home directory.

Expected outcome

I would expect it to default to creating a temporary directory for the caching and config directories, using them instead.

Additional information

The issue is caused by some calls to Path.home() in _get_config_or_cache_dir.

https://github.com/matplotlib/matplotlib/blob/e775274d7f1412bdb75414b1085f2cd7990490ad/lib/matplotlib/__init__.py#L532C1-L537C48

The simple solution would be to handle the potential RunTimeErrors from the Path.home() calls.

Additionally #12549 would probably also resolve this, bit that seems like a bigger push.

Operating system

Windows

Matplotlib Version

3.10.5

Matplotlib Backend

module://matplotlib_inline.backend_inline

Python version

3.13.7

Jupyter version

No response

Installation

pip

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions