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
- Set the missing environment variable before launching the process (e.g. set APPDATA=%USERPROFILE%\AppData\Roaming).
- Run under a normal interactive user account where the profile variables are populated.
- 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
- Ensure APPDATA/LOCALAPPDATA/ALLUSERSPROFILE are set for service/container accounts.
- Use WIN_PD_OVERRIDE_* to avoid depending on user-profile variables.
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
- should only be used on Unix
- Unknown CSIDL name: {csidl_name}
- SHGetKnownFolderPath returned NULL for {csidl_name}
- Could not determine appropriate file.
- Editor Subprocess exited with exit code {e.returncode}
AI-assisted analysis of pypa/pip@d7d0d0a394 (2026-08-04).
Data as JSON: /data/errors/11f264b3488355a2.json.
Report an issue: GitHub.