This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Provide a better error message when the file path is too long on Windows
Type: behavior Stage: patch review
Components: Windows Versions:
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: ZackerySpytz, brett.cannon, eryksun, paul.moore, steve.dower, tim.golden, zach.ware
Priority: normal Keywords: patch

Created on 2016-08-10 22:59 by brett.cannon, last changed 2022-04-11 14:58 by admin.

Pull Requests
URL Status Linked Edit
PR 20844 open ZackerySpytz, 2020-06-12 21:30
Messages (4)
msg272382 - (view) Author: Brett Cannon (brett.cannon) * (Python committer) Date: 2016-08-10 22:59
Windows has a max path length when the path doesn't start with r'\\?\'. When you hit that limit you get a FileNotFoundError but no explanation that it was because of some file path length. It would be nice to clarify this case in the exception message (probably by changing PyErr_SetExcFromWindowsErrWithFilenameObjects() in Python/errors.c).
msg272383 - (view) Author: Steve Dower (steve.dower) * (Python committer) Date: 2016-08-10 23:02
See https://github.com/pypa/pip/issues/3055 for an example of this error.

(Also note that there is a path limit of ~32k with the prefix, and that using it also disables a lot of standard path resolution algorithms, so simply adding it everywhere does not fix anything.)
msg272427 - (view) Author: Eryk Sun (eryksun) * (Python triager) Date: 2016-08-11 09:10
The NT runtime API RtlDosPathNameToRelativeNtPathName_U_WithStatus returns an informative error code, STATUS_NAME_TOO_LONG (0xC0000106). This gets translated to the less information but still useful Windows code ERROR_PATH_NOT_FOUND (0x0003). The CRT error table reduces this to ENOENT, so it's not readily distinguishable from ERROR_FILE_NOT_FOUND (0x0002).

The associated Windows error is still available via GetLastError when wopen returns:

    ucrtbase!wopen+0x22:
    00007ffb`222b5702 c3              ret
    0:000> ?? @$teb->LastErrorValue
    unsigned long 3

Currently io.FileIO calls PyErr_SetFromErrnoWithFilenameObjects. It could check for ERROR_PATH_NOT_FOUND when errno is ENOENT. In this case it could use a custom error message such as "No such path or path exceeds the maximum allowed length".
msg371429 - (view) Author: Eryk Sun (eryksun) * (Python triager) Date: 2020-06-13 00:13
Thanks for working on a PR, Zackery. Note that we can't rely on GetLastError() in PyErr_SetFromErrnoWithFilenameObjects. It may be called in contexts where the thread's LastErrorValue is no longer related to the C errno value. 

My suggestion in msg272427 was intended for _io_FileIO___init___impl in Modules/_io/fileio.c. Actually, a more useful change would be to modify this function to use the CRT _doserrno value [1]. Set _doserrno = 0 prior to calling _wopen. If it fails, set the exception via PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, _doserrno, nameobj). This will improve cases in which several system error codes are mapped to a single errno value such as ENOENT.

In theory, I like the idea of clarifying the error message for ERROR_PATH_NOT_FOUND (3) in PyErr_SetExcFromWindowsErrWithFilenameObjects. One concern I have is that this ignores the localization of the error message just for this single error code. It could extend the localized message with an English sentence, but is this too awkward? For example:

    El sistema no puede encontrar la ruta especificada. The path may 
    exceed the maximum allowed length.

[1]: https://docs.microsoft.com/en-us/cpp/c-runtime-library/errno-doserrno-sys-errlist-and-sys-nerr?view=vs-2019
History
Date User Action Args
2022-04-11 14:58:34adminsetgithub: 71916
2020-06-13 00:13:26eryksunsetmessages: + msg371429
2020-06-12 21:30:50ZackerySpytzsetkeywords: + patch
nosy: + ZackerySpytz

pull_requests: + pull_request20037
stage: test needed -> patch review
2016-08-11 09:10:29eryksunsetnosy: + eryksun
messages: + msg272427
2016-08-10 23:02:02steve.dowersetmessages: + msg272383
2016-08-10 22:59:55brett.cannoncreate