GeezerVison is showing github.com — Python 3.9.23 regression for `Path.resolve()` on Windows with `WinError 53` · Issue #136755 · python/cpython
Python 3.9.23 regression for Path.resolve() on Windows with WinError 53 #136755DescriptionBug report
Bug description:
from pathlib import Path
Path("//VBOXSVR/shared-folder").expanduser().resolve()
Raises FileNotFoundError: [WinError 53] The network path was not found: '\\\\VBOXSVR\\shared-folder\\'.
This appears to be a consequence of this backport:
By default the FileNotFoundError should be caught as a descendant of OSError, but since #135035 it is then also re-raised as it is not on the list of ignored Windows errors.
This passes on Python 3.10+ because 53: ERROR_BAD_NETPATH is included on the list since #27574:
|
# 53: ERROR_BAD_NETPATH |
|
# 65: ERROR_NETWORK_ACCESS_DENIED |
|
# 67: ERROR_BAD_NET_NAME (implies remote server unavailable) |
|
# 87: ERROR_INVALID_PARAMETER |
|
# 123: ERROR_INVALID_NAME |
|
# 161: ERROR_BAD_PATHNAME |
|
# 1005: ERROR_UNRECOGNIZED_VOLUME |
|
# 1920: ERROR_CANT_ACCESS_FILE |
|
# 1921: ERROR_CANT_RESOLVE_FILENAME (implies unfollowable symlink) |
|
allowed_winerror = 1, 2, 3, 5, 21, 32, 50, 53, 65, 67, 87, 123, 161, 1005, 1920, 1921 |
but it it was not backported to 3.9:
|
# 21: ERROR_NOT_READY (implies drive with no media) |
|
# 32: ERROR_SHARING_VIOLATION (probably an NTFS paging file) |
|
# 50: ERROR_NOT_SUPPORTED |
|
# 67: ERROR_BAD_NET_NAME (implies remote server unavailable) |
|
# 87: ERROR_INVALID_PARAMETER |
|
# 123: ERROR_INVALID_NAME |
|
# 1920: ERROR_CANT_ACCESS_FILE |
|
# 1921: ERROR_CANT_RESOLVE_FILENAME (implies unfollowable symlink) |
|
allowed_winerror = 1, 2, 3, 5, 21, 32, 50, 67, 87, 123, 1920, 1921 |
And since this code path is now used for Path.resolve() since #135035 was merged and backported I think that #27574 should be backported to other Python version to preserve old behaviour.
def normalized_uri(root_dir):
"""Attempt to make an LSP rootUri from a ContentsManager root_dir
Special care must be taken around windows paths: the canonical form of
windows drives and UNC paths is lower case
"""
> root_uri = Path(root_dir).expanduser().resolve().as_uri()
C:\Users\runneradmin\miniconda3\envs\test\lib\site-packages\jupyter_lsp\paths.py:16:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = WindowsPath('//VBOXSVR/shared-folder/'), strict = False
def resolve(self, strict=False):
"""
Make the path absolute, resolving all symlinks on the way and also
normalizing it (for example turning slashes into backslashes under
Windows).
"""
def check_eloop(e):
winerror = getattr(e, 'winerror', 0)
if e.errno == ELOOP or winerror == _WINERROR_CANT_RESOLVE_FILENAME:
raise RuntimeError("Symlink loop from %r" % e.filename)
try:
> s = self._accessor.realpath(self, strict=strict)
C:\Users\runneradmin\miniconda3\envs\test\lib\pathlib.py:1140:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
path = '\\\\VBOXSVR\\shared-folder\\'
def realpath(path, *, strict=False):
path = normpath(path)
if isinstance(path, bytes):
prefix = b'\\\\?\\'
unc_prefix = b'\\\\?\\UNC\\'
new_unc_prefix = b'\\\\'
cwd = os.getcwdb()
# bpo-38081: Special case for realpath(b'nul')
if normcase(path) == normcase(os.fsencode(devnull)):
return b'\\\\.\\NUL'
else:
prefix = '\\\\?\\'
unc_prefix = '\\\\?\\UNC\\'
new_unc_prefix = '\\\\'
cwd = os.getcwd()
# bpo-38081: Special case for realpath('nul')
if normcase(path) == normcase(devnull):
return '\\\\.\\NUL'
had_prefix = path.startswith(prefix)
if strict is ALLOW_MISSING:
ignored_error = FileNotFoundError
strict = True
elif strict:
ignored_error = ()
else:
ignored_error = OSError
if not had_prefix and not isabs(path):
path = join(cwd, path)
try:
path = _getfinalpathname(path)
initial_winerror = 0
except ignored_error as ex:
initial_winerror = ex.winerror
> path = _getfinalpathname_nonstrict(path,
ignored_error=ignored_error)
C:\Users\runneradmin\miniconda3\envs\test\lib\ntpath.py:663:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
path = '\\\\VBOXSVR\\shared-folder\\', ignored_error = <class 'OSError'>
def _getfinalpathname_nonstrict(path, ignored_error=OSError):
# These error codes indicate that we should stop resolving the path
# and return the value we currently have.
# 1: ERROR_INVALID_FUNCTION
# 2: ERROR_FILE_NOT_FOUND
# 3: ERROR_DIRECTORY_NOT_FOUND
# 5: ERROR_ACCESS_DENIED
# 21: ERROR_NOT_READY (implies drive with no media)
# 32: ERROR_SHARING_VIOLATION (probably an NTFS paging file)
# 50: ERROR_NOT_SUPPORTED
# 67: ERROR_BAD_NET_NAME (implies remote server unavailable)
# 87: ERROR_INVALID_PARAMETER
# 123: ERROR_INVALID_NAME
# 1920: ERROR_CANT_ACCESS_FILE
# 1921: ERROR_CANT_RESOLVE_FILENAME (implies unfollowable symlink)
allowed_winerror = 1, 2, 3, 5, 21, 32, 50, 67, 87, 123, 1920, 1921
# Non-strict algorithm is to find as much of the target directory
# as we can and join the rest.
tail = ''
while path:
try:
> path = _getfinalpathname(path)
E FileNotFoundError: [WinError 53] The network path was not found: '\\\\VBOXSVR\\shared-folder\\'
CPython versions tested on:
3.9
Operating systems tested on:
Windows
Linked PRs
ActivityStanFromIreland commented on Jul 18, 2025 picnixz commented on Jul 18, 2025 It's security-only but the backport was recent (June) so we should consider that the backport caused some relevant issues Reacted by Stan Ulbrych and Barney Gale StanFromIreland commented on Oct 2, 2025 cc @ambv since 3.9's last release is quite soon. StanFromIreland commented on Oct 12, 2025 I opened #140008 to backport 124ecd6 to 3.9 for @ambv if he wishes to fix this. Otherwise, feel free to close. ambv commented on Oct 20, 2025 Yeah, sorry I missed this for 3.9.24. We'll release one last 3.9.25 that will include this fix, if nothing else.
MetadataMetadataDevelopmentNo branches or pull requestsIssue actions
|