Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unknown error when copying files > 2GB using fs #30085

Closed
mklnz opened this issue Oct 23, 2019 · 18 comments · Fixed by #30783
Closed

Unknown error when copying files > 2GB using fs #30085

mklnz opened this issue Oct 23, 2019 · 18 comments · Fixed by #30783
Labels
fs Issues and PRs related to the fs subsystem / file system. libuv Issues and PRs related to the libuv dependency or the uv binding. macos Issues and PRs related to the macOS platform / OSX.

Comments

@mklnz
Copy link

mklnz commented Oct 23, 2019

  • Version: 10 through 13
  • Platform: Darwin Michaels-Mac-mini.local 19.0.0 Darwin Kernel Version 19.0.0: Wed Sep 25 20:18:50 PDT 2019; root:xnu-6153.11.26~2/RELEASE_X86_64 x86_64
  • Subsystem: fs
  • OS: macOS 10.15 Catalina

I'm having a very strange error on my Mac mini when using fs (both sync and async) copyFile to copy a file larger than 2GB. What's weird is on my MacBook Air with the same software setup there isn't any issues.

I created 2 files for testing using mkfile -n 1999m and mkfile -n 2g, then tried to copy them using node. the 1.999GB file worked fine and the 2GB file failed with unknown error. So there is a clear limit of 2GB here for some reason.

If this isn't a bug, how would one start to diagnose this further? The vague error certainly doesn't help. I've ruled out permission and drive space problems already, even reinstalled macOS from scratch but didn't help.

const fs = require('fs');
fs.copyFileSync('/Users/michael/Movies/wamp/1.mp4', '/Users/michael/Desktop/1.mp4');
internal/fs/utils.js:220
    throw err;
    ^

Error: UNKNOWN: unknown error, copyfile '/Users/michael/Movies/wamp/1.mp4' -> '/Users/michael/Desktop/1.mp4'
    at Object.copyFileSync (fs.js:1790:3)
    at Object.<anonymous> (/Users/michael/Development/homelab/meiti/copy-test.js:3:4)
    at Module._compile (internal/modules/cjs/loader.js:956:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:973:10)
    at Module.load (internal/modules/cjs/loader.js:812:32)
    at Function.Module._load (internal/modules/cjs/loader.js:724:14)
    at Function.Module.runMain (internal/modules/cjs/loader.js:1025:10)
    at internal/main/run_main_module.js:17:11 {   errno: -1429910540,   syscall: 'copyfile',   code: 'UNKNOWN',   path: '/Users/michael/Movies/wamp/1.mp4',   dest: '/Users/michael/Desktop/1.mp4' }

More info on Stackoverflow:
https://stackoverflow.com/questions/58500025/node-unknown-system-error-when-copying-large-files-over-2gb

@aduh95
Copy link
Contributor

aduh95 commented Oct 23, 2019

I am not able to reproduce the issue on Windows; maybe this is specific to macOS or AppleFS. What happens if you try to copy the file using cp command on the Terminal?

Also, does this issue happen only with copyFileSync or also with the other methods?

const fs = require("fs");

fs.copyFileSync("./2GB.bin", "./2GB-copySync.bin");

fs.copyFile(
  "./2GB.bin",
  "./2GB-copyASync.bin",
  console.log
);

fs.promises
  .copyFile("./2GB.bin", "./2GB-copyPromise.bin")
  .then(console.log, console.error);

@cjihrig
Copy link
Contributor

cjihrig commented Oct 23, 2019

This sounds like a bug in libuv. Quick experiment... can you try with Node 10.0.0. That version still had a macOS specific implementation, so I'd be curious to see if that version works.

@mklnz
Copy link
Author

mklnz commented Oct 23, 2019

This sounds like a bug in libuv. Quick experiment... can you try with Node 10.0.0. That version still had a macOS specific implementation, so I'd be curious to see if that version works.

Good test, yes using v10.0.0 works without any problems. So Node moved to libuv after 10.0.0? I wonder why it's fine on my laptop.

➜  test nvm use 10.0.0
Now using node v10.0.0 (npm v5.6.0)
➜  test node test.js
➜  test ls
2GB-copySync.bin 2GB.bin          test.js
➜  test
Now using node v13.0.1 (npm v6.12.0)
node test.js
internal/fs/utils.js:220
    throw err;
    ^

Error: UNKNOWN: unknown error, copyfile './2GB.bin' -> './2GB-copySync.bin'
    at Object.copyFileSync (fs.js:1806:3)
    at Object.<anonymous> (/Users/michael/Desktop/test/test.js:3:4)
    at Module._compile (internal/modules/cjs/loader.js:971:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1011:10)
    at Module.load (internal/modules/cjs/loader.js:822:32)
    at Function.Module._load (internal/modules/cjs/loader.js:730:14)
    at Function.Module.runMain (internal/modules/cjs/loader.js:1051:12)
    at internal/main/run_main_module.js:16:11 {
  errno: -2147483648,
  syscall: 'copyfile',
  code: 'UNKNOWN',
  path: './2GB.bin',
  dest: './2GB-copySync.bin'
}

@cjihrig
Copy link
Contributor

cjihrig commented Oct 23, 2019

So Node moved to libuv after 10.0.0?

Not quite. Node has been using libuv for years. The underlying implementation of fs.copyFile() is in libuv. The function uv_fs_copyfile() used to have a macOS specific implementation, but Apple had some bugs in it that we just couldn't tolerate. So now, macOS and all Unix platforms share an implementation.

I wonder why it's fine on my laptop.

My first guess is that the two machines use a different number of bits to represent the file size, or something, but it's just a guess.

@cclauss cclauss added the macos Issues and PRs related to the macOS platform / OSX. label Oct 23, 2019
@mklnz
Copy link
Author

mklnz commented Oct 24, 2019

I wonder why it's fine on my laptop.

My first guess is that the two machines use a different number of bits to represent the file size, or something, but it's just a guess.

Can I run any tests to verify this? I understand this problem might be hard to reproduce, if I can help in any way please let me know. Should I post this bug on the libuv repo also?

@cjihrig
Copy link
Contributor

cjihrig commented Oct 24, 2019

If you're comfortable with recompiling Node from source, I think it would be good to log the value here. That would tell us how many bytes libuv is trying to copy. If things were working properly, it should be the same as your file's size.

@mklnz
Copy link
Author

mklnz commented Oct 24, 2019

I put in a printf("%zu\n", bytes_to_send); in the source code and compiled Node. Using the built version I ran my test.js, this is the output (v13.01):

It does seem like it is the correct output, as that number is the exact bytes of the 2GB.bin
Though the strange thing here to note is the errno is just the negative of the bytes.

bytes_to_send: 2147483648

internal/fs/utils.js:220
    throw err;
    ^

Error: UNKNOWN: unknown error, copyfile './2GB.bin' -> './2GB-copySync.bin'
    at Object.copyFileSync (fs.js:1806:3)
    at Object.<anonymous> (/Users/michael/Desktop/test/test.js:3:4)
    at Module._compile (internal/modules/cjs/loader.js:971:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1011:10)
    at Module.load (internal/modules/cjs/loader.js:822:32)
    at Function.Module._load (internal/modules/cjs/loader.js:730:14)
    at Function.Module.runMain (internal/modules/cjs/loader.js:1051:12)
    at internal/main/run_main_module.js:16:11 {
  errno: -2147483648,
  syscall: 'copyfile',
  code: 'UNKNOWN',
  path: './2GB.bin',
  dest: './2GB-copySync.bin'
}

@cjihrig
Copy link
Contributor

cjihrig commented Oct 25, 2019

I think the next thing to check would be the values of r and errno after this line.

Out of curiosity - you mentioned that the code is working fine on your laptop. Is your laptop also running Catalina?

@mklnz
Copy link
Author

mklnz commented Oct 25, 2019

r: -1
errno: 38

errno 38 means ENOSYS, Function not implemented correct? Yes what's strange is my laptop has the exact same software environment. At this point I'm thinking it could be hardware related perhaps, but all other functions seem to work fine. I tried copying the same file using Ruby and it worked without issues.

@cjihrig
Copy link
Contributor

cjihrig commented Oct 26, 2019

errno 38 means ENOSYS

I believe 38 is ENOTSOCK on my machine. If that's the case on your machine, then execution would move to uv__fs_sendfile_emul() in that same file (that wouldn't happen if the error was ENOSYS). Can you confirm that you're ending up in uv__fs_sendfile_emul()? If so, I think this would be the place to debug.

@mklnz
Copy link
Author

mklnz commented Oct 27, 2019

Yes you're right, the error code is indeed ENOTSOCK and does hit uv__fs_sendfile_emul().
I placed a few printf after this line:

do
  n = write(out_fd, buf + nwritten, nread - nwritten);
while (n == -1 && errno == EINTR);
printf("EMUL n: %zd\n", n);
printf("EMUL errno: %d\n", errno);
if (n != -1) {
  nwritten += n;
  printf("EMUL nwritten: %zd\n", nwritten);
  continue;
}
printf("hit");

The last output before the Node error output in the console is:

EMUL n: 8192
EMUL errno: 0
EMUL nwritten: 8192
internal/fs/utils.js:220
    throw err;
    ^

Is it normal for nwritten to not be incremented?
Also it looks like the file has been written as I can see it in Finder, but disappears immediately after error output.

@cjihrig
Copy link
Contributor

cjihrig commented Oct 27, 2019

It seems like the file has been written as I can see it in Finder, but disappears immediately after error output.

When uv_fs_copyfile() encounters (or thinks it encounters) an error, it removes the destination file here. You should be able to comment out that block of code and see what the resulting file looks like.

@mklnz
Copy link
Author

mklnz commented Oct 27, 2019

Thanks for the help and quick response. I commented out that code block and checked the checksum of the original and destination files and they do seem to match:

➜  test openssl md5 2GB.bin
MD5(2GB.bin)= a981130cf2b7e09f4686dc273cf7187e
➜  test openssl md5 2GB-copySync.bin
MD5(2GB-copySync.bin)= a981130cf2b7e09f4686dc273cf7187e

The err in the out: label is -2147483648 which is again the size of the file.

cjihrig added a commit to cjihrig/libuv that referenced this issue Oct 29, 2019
The Unix/macOS uv__fs_copyfile() implementation falls back to
using uv_fs_sendfile(). This commit refactors the error handling
to use the sendfile() req's result field, which is an ssize_t
instead of using the return value, which is an int. The int
value was coming back as a negative number for some large files.

Refs: nodejs/node#30085
@cjihrig
Copy link
Contributor

cjihrig commented Oct 29, 2019

Proposed fix in libuv/libuv#2533.

@mklnz
Copy link
Author

mklnz commented Oct 30, 2019

Thanks for putting this fix in, I compiled using your commit and seems to be working. I will use a local version until it is merged.

cjihrig added a commit to cjihrig/libuv that referenced this issue Oct 30, 2019
The Unix/macOS uv__fs_copyfile() implementation falls back to
using uv_fs_sendfile(). This commit refactors the error handling
to use the sendfile() req's result field, which is an ssize_t
instead of using the return value, which is an int. The int
value was coming back as a negative number for some large files.

Refs: nodejs/node#30085
cjihrig added a commit to cjihrig/libuv that referenced this issue Oct 30, 2019
The Unix/macOS uv__fs_copyfile() implementation falls back to
using uv_fs_sendfile(). This commit refactors the error handling
to use the sendfile() req's result field, which is an ssize_t
instead of using the return value, which is an int. The int
value was coming back as a negative number for some large files.

Refs: nodejs/node#30085
PR-URL: libuv#2533
Reviewed-By: Santiago Gimeno <[email protected]>
Reviewed-By: Saúl Ibarra Corretgé <[email protected]>
Reviewed-By: Richard Lau <[email protected]>
@richardlau richardlau added libuv Issues and PRs related to the libuv dependency or the uv binding. fs Issues and PRs related to the fs subsystem / file system. labels Oct 31, 2019
@portah
Copy link

portah commented Nov 7, 2019

I had the same problem on Mojave iMac Pro (2018) nodejs 10.16. I used the proposed by @cjihrig 's patch and it works for now (nodejs 10.17.1-pre).

cjihrig added a commit to cjihrig/node that referenced this issue Dec 4, 2019
Notable changes:

- Fix handling of large files in `uv_fs_copyfile()`.
  Fixes: nodejs#30085
- Fix Android build errors.
- uv_sleep() has been added.
- uv_interface_addresses() IPv6 netmask support has been fixed.
  Fixes: nodejs#30504
- uv_fs_mkstemp() has been added.
@cjihrig cjihrig closed this as completed in 5d2944d Dec 6, 2019
targos pushed a commit that referenced this issue Dec 9, 2019
Notable changes:

- Fix handling of large files in uv_fs_copyfile().
  Fixes: #30085
- Fix Android build errors.
- uv_sleep() has been added.
- uv_interface_addresses() IPv6 netmask support has been fixed.
  Fixes: #30504
- uv_fs_mkstemp() has been added.

PR-URL: #30783
Fixes: #30085
Fixes: #30504
Reviewed-By: Tobias Nießen <[email protected]>
Reviewed-By: Daniel Bevenius <[email protected]>
Reviewed-By: Richard Lau <[email protected]>
Reviewed-By: Santiago Gimeno <[email protected]>
Reviewed-By: Jiawen Geng <[email protected]>
Reviewed-By: Rich Trott <[email protected]>
Reviewed-By: Trivikram Kamat <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
Reviewed-By: Ben Noordhuis <[email protected]>
targos pushed a commit that referenced this issue Jan 14, 2020
Notable changes:

- Fix handling of large files in uv_fs_copyfile().
  Fixes: #30085
- Fix Android build errors.
- uv_sleep() has been added.
- uv_interface_addresses() IPv6 netmask support has been fixed.
  Fixes: #30504
- uv_fs_mkstemp() has been added.

PR-URL: #30783
Fixes: #30085
Fixes: #30504
Reviewed-By: Tobias Nießen <[email protected]>
Reviewed-By: Daniel Bevenius <[email protected]>
Reviewed-By: Richard Lau <[email protected]>
Reviewed-By: Santiago Gimeno <[email protected]>
Reviewed-By: Jiawen Geng <[email protected]>
Reviewed-By: Rich Trott <[email protected]>
Reviewed-By: Trivikram Kamat <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
Reviewed-By: Ben Noordhuis <[email protected]>
BethGriggs pushed a commit that referenced this issue Feb 6, 2020
Notable changes:

- Fix handling of large files in uv_fs_copyfile().
  Fixes: #30085
- Fix Android build errors.
- uv_sleep() has been added.
- uv_interface_addresses() IPv6 netmask support has been fixed.
  Fixes: #30504
- uv_fs_mkstemp() has been added.

PR-URL: #30783
Fixes: #30085
Fixes: #30504
Reviewed-By: Tobias Nießen <[email protected]>
Reviewed-By: Daniel Bevenius <[email protected]>
Reviewed-By: Richard Lau <[email protected]>
Reviewed-By: Santiago Gimeno <[email protected]>
Reviewed-By: Jiawen Geng <[email protected]>
Reviewed-By: Rich Trott <[email protected]>
Reviewed-By: Trivikram Kamat <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
Reviewed-By: Ben Noordhuis <[email protected]>
BethGriggs pushed a commit to BethGriggs/node that referenced this issue Feb 26, 2020
Notable changes:

- Fix handling of large files in uv_fs_copyfile().
  Fixes: nodejs#30085
- Fix Android build errors.
- uv_sleep() has been added.
- uv_interface_addresses() IPv6 netmask support has been fixed.
  Fixes: nodejs#30504
- uv_fs_mkstemp() has been added.

PR-URL: nodejs#30783
Fixes: nodejs#30085
Fixes: nodejs#30504
Reviewed-By: Tobias Nießen <[email protected]>
Reviewed-By: Daniel Bevenius <[email protected]>
Reviewed-By: Richard Lau <[email protected]>
Reviewed-By: Santiago Gimeno <[email protected]>
Reviewed-By: Jiawen Geng <[email protected]>
Reviewed-By: Rich Trott <[email protected]>
Reviewed-By: Trivikram Kamat <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
Reviewed-By: Ben Noordhuis <[email protected]>
BethGriggs pushed a commit that referenced this issue Mar 2, 2020
Notable changes:

- Fix handling of large files in uv_fs_copyfile().
  Fixes: #30085
- Fix Android build errors.
- uv_sleep() has been added.
- uv_interface_addresses() IPv6 netmask support has been fixed.
  Fixes: #30504
- uv_fs_mkstemp() has been added.

PR-URL: #30783
Backport-PR-URL: #31969
Fixes: #30085
Fixes: #30504
Reviewed-By: Tobias Nießen <[email protected]>
Reviewed-By: Daniel Bevenius <[email protected]>
Reviewed-By: Richard Lau <[email protected]>
Reviewed-By: Santiago Gimeno <[email protected]>
Reviewed-By: Jiawen Geng <[email protected]>
Reviewed-By: Rich Trott <[email protected]>
Reviewed-By: Trivikram Kamat <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
Reviewed-By: Ben Noordhuis <[email protected]>
@Octoroboto
Copy link

Sorry new to building apps with Node.js and electron. How do I go about fixing this? I've updated to the latest version of node and the problem persists.

@wsegatto
Copy link

[2]

Sorry new to building apps with Node.js and electron. How do I go about fixing this? I've updated to the latest version of node and the problem persists.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
fs Issues and PRs related to the fs subsystem / file system. libuv Issues and PRs related to the libuv dependency or the uv binding. macos Issues and PRs related to the macOS platform / OSX.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants