-
Notifications
You must be signed in to change notification settings - Fork 7.3k
BUG: fs.rename gives incorrect error message on error #685
Comments
this is difficult to resolve because ENOENT doesn't distinguish between the two errors:
|
Maybe we could change how ENOENT is handled in this case, and report both filenames? |
Same behavior can be seen in fs.symlink, or any other fs function that takes two paths. |
sure |
v0.5.10:
|
Is there any function, at the moment, that needs more than 2 paths as input? I was looking at the code and I think I can add a Just started looking at the code so, this might be complete nonsense... if you like the idea let me know, I'll finish it and submit for review ;) |
@DiogoNeves Off the top of my head: rename, symlink, link. (Technically, "symlink" doesn't require two paths, since the linkdata argument doesn't have to exist yet.) |
I know this doesn't mean much hehe but I'm excited with the possibility of my first contribution! :) |
Actually, quick question. Thanks |
@ry now I know what you mean... the error returned when either file doesn't exist is exactly the same. My previous fix was stupid hehe :)
I'm still investigating other possible solutions, I don't like 'impossible' things hehe and it's great to dig around the code. EDIT: And the extra easy and safe option goes to... Display this error message:
What do you think? |
Ok, after irc chatting with @bnoordhuis I tried to come up with a way to pass new_path around without creating yet another copy. Obviously I didn't start changing all that code ;) just want to discuss it as a possible solution. EDIT: Sorry, @bnoordhuis I don't know when will I be online tomorrow so I shared right now ;) |
@DiogoNeves: A patch should not touch libuv or libeio. Duplicate data makes me sad but I'll cope. |
I think I took it more as a challenge, my bad ;) |
Testing against v0.8.15, the error message doesn't seem to have the same format:
The |
Semi-related to #4314 though the patch for that issue is targeted at v0.8. As a fix for this issue would require adding a property to the Error object, it's arguably an API change and not suitable for v0.8.
That's because of a V8 change where Error properties are no longer enumerable. I can't find the commit but it's been like that for a while now. |
Would be great to fix, thought I am gonna jump out of the window before finding this issue.... |
Can confirm this is a problem on linux. Geez, I just wanted to explode because of this missleading error. This needs to be fixed as soon as possible. Has there been any headway towards the actual implementation? Or rather, what is the status of a fix? |
@bnoordhuis Here's a horribly ugly patch, and only fixes the sync part, but want your thoughts on the general approach: diff --git a/src/node_file.cc b/src/node_file.cc
index 3b287ec..6e11d3e 100644
--- a/src/node_file.cc
+++ b/src/node_file.cc
@@ -288,8 +288,14 @@ struct fs_req_wrap {
__VA_ARGS__, \
NULL); \
if (err < 0) { \
+ int err2 = 0; \
+ if (dest != NULL) { \
+ uv_fs_t stat_wrap; \
+ err2 = uv_fs_stat(env->event_loop(), &stat_wrap, dest, NULL); \
+ } \
if (dest != NULL && \
- (err == UV_EEXIST || \
+ (err2 < 0 || \
+ err == UV_EEXIST || \
err == UV_ENOTEMPTY || \
err == UV_EPERM)) { \
return env->ThrowUVException(err, #func, "", dest); \ IMO once code reaches an error path performance is secondary. So the sync stat to check if the file exists shouldn't matter. Thoughts? |
I don't know if that's true. Take for example the way fs.statSync() is used in require(). #8189 is tangentially related to that. |
@bnoordhuis fair enough. Other than |
Sadly, no. It's bad design of the UNIX API, really. (Heresy, I know.) |
@bnoordhuis haha, okay. and would you consider it a bad idea to do a "quick" |
In the case of an error, knowing the error is more beneficial than a very low efficiency hit. Are there any objections to that statement? Also, In the cases where this is a production error and the possibility of a file not existing at runtime is greater than none, developers will be checking for file existence anyways (avoiding the error being thrown in the first place). In other words, this patch would only effect performance during development. |
Well, there's the performance issue to consider but another gotcha is the race window between the two system calls. If |
@bnoordhuis Oy, and there you go pointing out the obvious but PITA edge cases. ;P So, seems like it's technically impossible to be absolutely certain what file didn't exist at the time |
Haha, that's no fun. |
UP, really confusing bug This bug took me some minutes, to figure out that the last subfolder in the destination was not present |
Ran into a similar problem a few years ago in a different system. The only solution we came up with at the time was to take the performance hit and acknowledge the inherent race condition in the documentation. The warning to developers was basically, "if it hurts when you do that, then don't do it." Improving the error report as @trevnorris suggested in comment 54381951 would be good. |
@piscisaureus is this still an issue in io.js? |
Confirmed still exists on v0.12 for ubuntu |
Confirmed issues exists in io.js as well |
Libuv (at least on windows, don't know about unix) can't tell whether an error is related to the 'source' or 'target' path. Therefore, the only option we have is to display both paths. io.js does that:
(@mhdawson - you reported that this is still an issue in io.js, but in fact this was fixed late January in nodejs/node@bc2c85c. I suspect that you may have accidentally tested node or a really old io.js version) |
Ok, so the question that remains is: do we want to backport this fix into v0.12 or joyent/node master or pick it up when we move to the converged stream? (I'm inclined to wait until we moved to the converged stream) |
I think I ran on a recent enough io.js but when we reviewed the message the initial thought was that it still was not clear enough. Given your explanation about not being able to tell which path is the problem I can see its the best we can do. Since its a P3 it should be able to wait until the converged stream. |
Agreed on waiting for the converged stream. |
at this point, I'm inclined to close this here. If someone wishes to backport the io.js fix to v0.12 then so be it, but the priority is low. |
Try this:
test.js
node test.js
expected:
AJ ONeal
The text was updated successfully, but these errors were encountered: