pypa/pip · error · ValueError
SHGetKnownFolderPath returned NULL for {csidl_name}
Error message
SHGetKnownFolderPath returned NULL for {csidl_name} What it means
Raised as ValueError by the ctypes resolve() when the Windows SHGetKnownFolderPath API call returned a NULL pointer for the given CSIDL/known-folder GUID. A NULL result means the system could not resolve that known folder (e.g. it does not exist on this Windows edition or the user profile lacks it).
Source
Thrown at src/pip/_vendor/platformdirs/windows.py:363
kernel32.GetShortPathNameW.argtypes = [wintypes.LPWSTR, wintypes.LPWSTR, wintypes.DWORD]
def resolve(csidl_name: str) -> str:
folder_guid = _KNOWN_FOLDER_GUIDS.get(csidl_name)
if folder_guid is None:
msg = f"Unknown CSIDL name: {csidl_name}"
raise ValueError(msg)
guid = _GUID()
ole32.CLSIDFromString(folder_guid, byref(guid))
path_ptr = wintypes.LPWSTR()
shell32.SHGetKnownFolderPath(byref(guid), _KF_FLAG_DONT_VERIFY, None, byref(path_ptr))
result = path_ptr.value
ole32.CoTaskMemFree(path_ptr)
if result is None:
msg = f"SHGetKnownFolderPath returned NULL for {csidl_name}"
raise ValueError(msg)
if any(ord(c) > 255 for c in result): # ruff:ignore[magic-value-comparison]
buf = create_unicode_buffer(1024)
if kernel32.GetShortPathNameW(result, buf, 1024):
result = buf.value
return result
return resolve
def get_win_folder_via_ctypes(csidl_name: str) -> str:
"""Get folder via :func:`SHGetKnownFolderPath`.
See https://learn.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shgetknownfolderpath.
"""
return _build_get_win_folder_via_ctypes()(csidl_name)View on GitHub (pinned to d7d0d0a394)
Solutions
- Set the corresponding WIN_PD_OVERRIDE_<NAME> environment variable to a concrete path so platformdirs skips the API call.
- Run under an interactive user account whose profile has the folder materialized.
- Wrap the call in try/except ValueError and fall back to a sensible default path.
Example fix
# before
path = get_win_folder('CSIDL_DOWNLOADS') # NULL -> ValueError
# after
try:
path = get_win_folder('CSIDL_DOWNLOADS')
except ValueError:
path = os.path.join(os.environ['USERPROFILE'], 'Downloads') Defensive patterns
Strategy: fallback
Validate before calling
null
Type guard
null
Try / catch
try:
path = get_win_folder(csidl_name)
except ValueError as e:
if 'SHGetKnownFolderPath returned NULL' in str(e):
path = os.path.join(os.environ.get('USERPROFILE',''), default_subdir(csidl_name))
raise Prevention
- Set WIN_PD_OVERRIDE_<NAME> for known folders missing on Server Core/service accounts.
- Provide a fallback path for known folders that may be unavailable.
When it happens
Trigger: resolve(csidl_name) calls shell32.SHGetKnownFolderPath with the folder GUID; path_ptr.value comes back None, so the folder path is unavailable on the running Windows system.
Common situations: Server Core or a stripped Windows SKU that does not provide a particular known folder, a corrupted/missing user profile (e.g. Downloads not materialized), or a service account without a populated profile.
Related errors
- Unknown CSIDL name: {csidl_name}
- should only be used on Unix
- Unset environment variable: {env_var_name}
- To modify pip, please run the following command:\n{formatted
- path '%s' cannot be absolute
AI-assisted analysis of pypa/pip@d7d0d0a394 (2026-08-04).
Data as JSON: /data/errors/056b9b54b246cadf.json.
Report an issue: GitHub.