pypa/pip · error · ValueError

Unset environment variable: {env_var_name}

Error message

Unset environment variable: {env_var_name}

What it means

Raised as ValueError by get_win_folder_from_env_vars when a CSIDL constant resolves to an env-var name (APPDATA / LOCALAPPDATA / ALLUSERSPROFILE) but that environment variable is not set in os.environ. The message names the missing variable so the user knows what to provide.

Source

Thrown at src/pip/_vendor/platformdirs/windows.py:212

def get_win_folder_from_env_vars(csidl_name: str) -> str:
    """Get folder from environment variables."""
    result = get_win_folder_if_csidl_name_not_env_var(csidl_name)
    if result is not None:
        return result

    env_var_name = {
        "CSIDL_APPDATA": "APPDATA",
        "CSIDL_COMMON_APPDATA": "ALLUSERSPROFILE",
        "CSIDL_LOCAL_APPDATA": "LOCALAPPDATA",
    }.get(csidl_name)
    if env_var_name is None:
        msg = f"Unknown CSIDL name: {csidl_name}"
        raise ValueError(msg)
    result = os.environ.get(env_var_name)
    if result is None:
        msg = f"Unset environment variable: {env_var_name}"
        raise ValueError(msg)
    return result


def get_win_folder_if_csidl_name_not_env_var(csidl_name: str) -> str | None:  # ruff:ignore[too-many-return-statements]
    """Get a folder for a CSIDL name that does not exist as an environment variable."""
    if csidl_name == "CSIDL_PERSONAL":
        return os.path.join(os.path.normpath(os.environ["USERPROFILE"]), "Documents")  # ruff:ignore[os-path-join]

    if csidl_name == "CSIDL_DOWNLOADS":
        return os.path.join(os.path.normpath(os.environ["USERPROFILE"]), "Downloads")  # ruff:ignore[os-path-join]

    if csidl_name == "CSIDL_MYPICTURES":
        return os.path.join(os.path.normpath(os.environ["USERPROFILE"]), "Pictures")  # ruff:ignore[os-path-join]

    if csidl_name == "CSIDL_MYVIDEO":
        return os.path.join(os.path.normpath(os.environ["USERPROFILE"]), "Videos")  # ruff:ignore[os-path-join]

    if csidl_name == "CSIDL_MYMUSIC":

View on GitHub (pinned to d7d0d0a394)

Solutions

  1. Set the missing environment variable before launching the process (e.g. set APPDATA=%USERPROFILE%\AppData\Roaming).
  2. Run under a normal interactive user account where the profile variables are populated.
  3. Provide a WIN_PD_OVERRIDE_<NAME> env var so platformdirs uses the override path instead of the unset variable.

Example fix

# before
# APPDATA unset -> ValueError: Unset environment variable: APPDATA

# after (shell, before running python)
set APPDATA=%USERPROFILE%\AppData\Roaming
python app.py
Defensive patterns

Strategy: validation

Validate before calling

import os
ENV_FOR = {'CSIDL_APPDATA': 'APPDATA', 'CSIDL_COMMON_APPDATA': 'ALLUSERSPROFILE', 'CSIDL_LOCAL_APPDATA': 'LOCALAPPDATA'}
env_var = ENV_FOR.get(csidl_name)
if env_var and env_var not in os.environ:
    raise EnvironmentError(f'set {env_var} before resolving {csidl_name}')

Type guard

def env_var_set(name: str) -> bool:
    import os
    return name in os.environ

Try / catch

try:
    p = get_win_folder_from_env_vars(name)
except ValueError as e:
    if 'Unset environment variable' in str(e):
        var = str(e).split(':')[-1].strip()
        os.environ[var] = default_for(var)  # set then retry
    raise

Prevention

When it happens

Trigger: On Windows (or a Windows-like env without ctypes/winreg) the folder resolver falls back to environment variables; APPDATA/LOCALAPPDATA/ALLUSERSPROFILE is unset, so os.environ.get returns None and ValueError is raised.

Common situations: Running as a service account or in a container/minimal Windows env where these user-profile variables are not populated, or a corrupted user profile.

Related errors


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