You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
'ImportError: DLL load failed while importing xxxxxxx: The filename or extension is too long' with LongPathsEnabled #126929
Without that registry key set import of module at long path fails with ModuleNotFoundError: No module named 'xxxxxxxxx' or opening file fails with FileNotFoundError: [Errno 2] No such file or directory. With registry key set the limit is extended and 260 symbols long paths are working fine.
The issue I've found that importing binary Python extension seems to break on long paths (250 symbols seems to be max length) even with LongPathsEnabled, see the snippet below.
To reproduce this, you can setup some very long path (>250 symbols) in your site-packages and put in that directory one empty .py file (in my case it's "yyyy...yyyyyyyyyyy.py") and some .pyd file that it's importing fine without any other binary dependencies - in my case I was using _yaml.cp311-win_amd64.pyd I got from https://pypi.org/project/PyYAML/#files.
# Importing just .py module.importxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyasscriptprint(len(script.__file__)) # 298. Doesn't seem to have limit at 250-260 symbols.# Importing .pyd.importxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx._yamlasyamlprint(len(yaml.__file__)) # 250. seems to be the max.
Found this issue working with Blender (related issue) - Blender comes with it's own Python and there's an option to store some of Blender addons dependencies next to blender.exe, so it can be virtually anywhere on the computer and paths can get very long.
This type of path is composed of components separated by backslashes, each up to the value returned in the lpMaximumComponentLength parameter of the GetVolumeInformation function (this value is commonly 255 characters)
So no individual directory or file name can have more than that many characters, even though the entire path might exceed that length. That's just an OS limit, and there's no getting around it.
Having a quick look through the Blender issue, it does seem that the issue there is some executables probably aren't correctly manifested to allow long paths. It's annoying that you have to do that, but again, that's the way Windows made it work (ironically, the first release of Windows with the long paths feature didn't check the manifests, so everything got it automatically and life was great! 😆 ).
I'm not sure there's anything we can do here, but let's leave the issue open for a couple of days in case someone has an idea. (I don't particularly want to try and generate a better error message than Windows itself, though in this case it's possible because the actual limit is available at runtime.)
This type of path is composed of components separated by backslashes, each up to the value returned in the lpMaximumComponentLength parameter of the GetVolumeInformation function (this value is commonly 255 characters)
So no individual directory or file name can have more than that many characters, even though the entire path might exceed that length. That's just an OS limit, and there's no getting around it.
The issue I report here is about .pyd filepaths being limited to around 250 symbols in overall size, not in a single segment.
Having a quick look through the Blender issue, it does seem that the issue there is some executables probably aren't correctly manifested to allow long paths
It was indeed the original issue with Blender with importing .py modules that's resolved with changing manifest, resolving helped figuring that there is another issue specifically with .pyd's.
I can reproduce, but it's deep inside Windows's dependency loader. As far as I can tell, it can only be fixed by an OS update.
It does appear to only occur when the DLL has an embedded manifest. Doesn't seem to matter what's in the manifest, but if it's there then it apparently tries to load something through the path and hits a too-long error.
I've reached out to the team who owns this part of the OS to see what they say. Removing the manifest entirely may be the right option, but I want to confirm that with the part of the OS that relies on it before making that general advice.
I also experience that,
Is there any progress from the OS team? Or anyone has other ideas on how to solve this ? I experience this when using Bazel which creates very long path names
Or are you aware of some bypass to just never use .pyd?
No, no progress here. It seems that the code in question is so old that nobody is confident to update it.
The best workaround seems to be disabling embedded manifests entirely in PYD builds. That ought to be fine - the manifest is basically only relevant in an EXE these days - but it may require a more advanced build backend to support it.
A possible workaround mentioned in Maximum Path Length Limitation is that, given an absolute and normalized path, we can prepend \\?\ to it to bypass the MAX_PATH limitation:
The "\\?\" prefix can also be used with paths constructed according to the universal naming convention (UNC). To specify such a path using UNC, use the "\\?\UNC\" prefix. For example, "\\?\UNC\server\share", where "server" is the name of the computer and "share" is the name of the shared folder. These prefixes are not used as part of the path itself. They indicate that the path should be passed to the system with minimal modification, which means that you cannot use forward slashes to represent path separators, or a period to represent the current directory, or double dots to represent the parent directory. Because you cannot use the "\\?\" prefix with a relative path, relative paths are always limited to a total of MAX_PATH characters.
I tested this on Windows build 26100.9168 and confirmed that this workaround works with LoadLibraryExW. So I created the following patch (agsinst v3.14.6) to help resolve this issue in my TensorFlow build process:
Details
diff --git a/Python/dynload_win.c b/Python/dynload_win.c
index 6324063401e..b45168f229f 100644
--- a/Python/dynload_win.c+++ b/Python/dynload_win.c@@ -10,6 +10,11 @@
#include "patchlevel.h" // PY_MAJOR_VERSION
#include <windows.h>
+#include <assert.h>+#include <stdint.h>+#include <string.h>+#include <wchar.h>+
const char *_PyImport_DynLoadFiletab[] = {
PYD_TAGGED_SUFFIX,
PYD_UNTAGGED_SUFFIX,
@@ -145,6 +150,41 @@ static char *GetPythonImport (HINSTANCE hModule)
return NULL;
}
+static HMODULE+_Py_LoadLibraryExW(LPCWSTR path, HANDLE file, DWORD flags) {+ assert(path != NULL);+ assert(wcschr(path, L'/') == NULL);+ assert(file == NULL);+ do {+ if (_Py_isabs(path) == 0) {+ break;+ }+ if (path[0] == L'\\') {+ // Exclude UNC or device paths.+ break;+ }+ static const wchar_t prefix[] = L"\\\\?\\";+ static const size_t prefix_size =+ sizeof(prefix) / sizeof(prefix[0]) - 1;+ const size_t path_size = wcslen(path);+ assert(path_size <= SIZE_MAX - prefix_size - 1);+ wchar_t *const extended_path =+ PyMem_New(wchar_t, prefix_size + path_size + 1);+ if (extended_path == NULL) {+ break;+ }+ memcpy(extended_path, prefix, prefix_size * sizeof(wchar_t));+ _Py_normpath(memcpy(extended_path + prefix_size,+ path,+ (path_size + 1) * sizeof(wchar_t)),+ path_size);+ const HMODULE module = LoadLibraryExW(extended_path, file, flags);+ PyMem_Del(extended_path);+ return module;+ } while (0);+ return LoadLibraryExW(path, file, flags);+}+
#ifdef Py_ENABLE_SHARED
/* Load python3.dll before loading any extension module that might refer
to it. That way, we can be sure that always the python3.dll corresponding
@@ -171,7 +211,7 @@ _Py_CheckPython3(void)
wchar_t *p = wcsrchr(py3path, L'\\');
if (p) {
wcscpy(p + 1, PY3_DLLNAME);
- hPython3 = LoadLibraryExW(py3path, NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);+ hPython3 = _Py_LoadLibraryExW(py3path, NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
if (hPython3 != NULL) {
return 1;
}
@@ -193,7 +233,7 @@ _Py_CheckPython3(void)
if (config->prefix) {
wcscpy_s(py3path, MAXPATHLEN, config->prefix);
if (py3path[0] && _Py_add_relfile(py3path, L"DLLs\\" PY3_DLLNAME, MAXPATHLEN) >= 0) {
- hPython3 = LoadLibraryExW(py3path, NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);+ hPython3 = _Py_LoadLibraryExW(py3path, NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
}
}
return hPython3 != NULL;
@@ -231,11 +271,9 @@ dl_funcptr _PyImport_FindSharedFuncptrWindows(const char *prefix,
to avoid DLL preloading attacks and enable use of the
AddDllDirectory function. We add SEARCH_DLL_LOAD_DIR to
ensure DLLs adjacent to the PYD are preferred. */
- Py_BEGIN_ALLOW_THREADS- hDLL = LoadLibraryExW(wpathname, NULL,- LOAD_LIBRARY_SEARCH_DEFAULT_DIRS |- LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR);- Py_END_ALLOW_THREADS+ hDLL = _Py_LoadLibraryExW(wpathname, NULL,+ LOAD_LIBRARY_SEARCH_DEFAULT_DIRS |+ LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR);
PyMem_Free(wpathname);
#ifdef MS_WINDOWS_DESKTOP
PS For the curious, the cause of this issue is that, when loading a DLL with a manifest, a synthesized path is produced by appending .2.Config to the DLL path. If that path exceeds MAX_PATH, the NT_STATUS_NAME_TOO_LONG error is produced by RtlDosPathNameToNtPathName_U_WithStatus. A path prefixed with \\?\ does not go through that function, so everything works as expected. Also note that the error originates from csrss.exe, so kernel-mode debugging has to be used to inspect it.
I think we'd probably accept a PR along those lines, though I'd prefer it to only try modifying the path in the cases where LoadLibraryExW has already failed, and we can confirm that the file exists and is a regular file (which shouldn't hit the manifest issue). If those conditions are met, then try again with \\?\ prefixed.
Activity
zooba commentedon Nov 18, 2024
Yes, even with long paths enabled, Windows still has a per-segment limit: (from https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation)
So no individual directory or file name can have more than that many characters, even though the entire path might exceed that length. That's just an OS limit, and there's no getting around it.
Having a quick look through the Blender issue, it does seem that the issue there is some executables probably aren't correctly manifested to allow long paths. It's annoying that you have to do that, but again, that's the way Windows made it work (ironically, the first release of Windows with the long paths feature didn't check the manifests, so everything got it automatically and life was great! 😆 ).
zooba commentedon Nov 18, 2024
I'm not sure there's anything we can do here, but let's leave the issue open for a couple of days in case someone has an idea. (I don't particularly want to try and generate a better error message than Windows itself, though in this case it's possible because the actual limit is available at runtime.)
Andrej730 commentedon Nov 18, 2024
@zooba
The issue I report here is about .pyd filepaths being limited to around 250 symbols in overall size, not in a single segment.
It was indeed the original issue with Blender with importing .py modules that's resolved with changing manifest, resolving helped figuring that there is another issue specifically with .pyd's.
zooba commentedon Nov 18, 2024
Ah, thanks for clarifying.
I can reproduce, but it's deep inside Windows's dependency loader. As far as I can tell, it can only be fixed by an OS update.
It does appear to only occur when the DLL has an embedded manifest. Doesn't seem to matter what's in the manifest, but if it's there then it apparently tries to load something through the path and hits a too-long error.
I've reached out to the team who owns this part of the OS to see what they say. Removing the manifest entirely may be the right option, but I want to confirm that with the part of the OS that relies on it before making that general advice.
LavaTime commentedon Jul 13, 2025
I also experience that,
Is there any progress from the OS team? Or anyone has other ideas on how to solve this ? I experience this when using Bazel which creates very long path names
Or are you aware of some bypass to just never use .pyd?
zooba commentedon Jul 28, 2025
No, no progress here. It seems that the code in question is so old that nobody is confident to update it.
The best workaround seems to be disabling embedded manifests entirely in PYD builds. That ought to be fine - the manifest is basically only relevant in an EXE these days - but it may require a more advanced build backend to support it.
chengfeng-xie commentedon Aug 28, 2026
A possible workaround mentioned in Maximum Path Length Limitation is that, given an absolute and normalized path, we can prepend
\\?\to it to bypass theMAX_PATHlimitation:I tested this on Windows build 26100.9168 and confirmed that this workaround works with
LoadLibraryExW. So I created the following patch (agsinstv3.14.6) to help resolve this issue in my TensorFlow build process:Details
PS For the curious, the cause of this issue is that, when loading a DLL with a manifest, a synthesized path is produced by appending
.2.Configto the DLL path. If that path exceedsMAX_PATH, theNT_STATUS_NAME_TOO_LONGerror is produced byRtlDosPathNameToNtPathName_U_WithStatus. A path prefixed with\\?\does not go through that function, so everything works as expected. Also note that the error originates fromcsrss.exe, so kernel-mode debugging has to be used to inspect it.zooba commentedon Aug 31, 2026
I think we'd probably accept a PR along those lines, though I'd prefer it to only try modifying the path in the cases where
LoadLibraryExWhas already failed, and we can confirm that the file exists and is a regular file (which shouldn't hit the manifest issue). If those conditions are met, then try again with\\?\prefixed.