pypa/pip · error · ValueError

Unknown CSIDL name: {csidl_name}

Error message

Unknown CSIDL name: {csidl_name}

What it means

Raised as ValueError by get_win_folder_from_env_vars when the requested csidl_name is neither handled by get_win_folder_if_csidl_name_not_env_var nor present in the {CSIDL_APPDATA, CSIDL_COMMON_APPDATA, CSIDL_LOCAL_APPDATA} env-var mapping. The message echoes the unknown CSIDL constant.

Source

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

    def site_runtime_dir(self) -> str:
        """Runtime directory shared by users, same as `user_runtime_dir`."""
        return self.user_runtime_dir


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]

View on GitHub (pinned to d7d0d0a394)

Solutions

  1. Pass one of the supported CSIDL constants: CSIDL_APPDATA, CSIDL_COMMON_APPDATA, CSIDL_LOCAL_APPDATA (or the not-env-var ones like CSIDL_PERSONAL).
  2. Avoid calling the internal get_win_folder_from_env_vars directly; use the public Windows()/platformdirs API which only emits valid constants.
  3. Correct the typo in any WIN_PD_OVERRIDE_* environment variable name.

Example fix

# before
get_win_folder_from_env_vars('CSIDL_Dekstop')  # ValueError

# after
get_win_folder_from_env_vars('CSIDL_LOCAL_APPDATA')
Defensive patterns

Strategy: validation

Validate before calling

KNOWN = {'CSIDL_APPDATA', 'CSIDL_COMMON_APPDATA', 'CSIDL_LOCAL_APPDATA',
          'CSIDL_PERSONAL', 'CSIDL_DOWNLOADS', 'CSIDL_MYPICTURES',
          'CSIDL_MYVIDEO', 'CSIDL_MYMUSIC', 'CSIDL_PROGRAMS', 'CSIDL_COMMON_PROGRAMS'}
if csidl_name in KNOWN:
    get_win_folder_from_env_vars(csidl_name)

Type guard

def is_known_csidl(name: str) -> bool:
    return name in {'CSIDL_APPDATA','CSIDL_COMMON_APPDATA','CSIDL_LOCAL_APPDATA',
                    'CSIDL_PERSONAL','CSIDL_DOWNLOADS','CSIDL_MYPICTURES',
                    'CSIDL_MYVIDEO','CSIDL_MYMUSIC','CSIDL_PROGRAMS','CSIDL_COMMON_PROGRAMS'}

Try / catch

try:
    p = get_win_folder_from_env_vars(name)
except ValueError as e:
    if 'Unknown CSIDL name' in str(e):
        # name is unsupported; use a default
        ...
    raise

Prevention

When it happens

Trigger: Calling get_win_folder_from_env_vars(csidl_name) with a CSIDL constant not in the supported set (e.g. a typo like 'CSIDL_Dekstop' or an unsupported constant). This path is selected when neither ctypes nor winreg is available.

Common situations: A user override or custom code passing a wrong CSIDL name; running under a stripped-down Windows-like environment (no ctypes/winreg) so the env-var fallback path is used with an invalid name.

Related errors


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