Error: EXDEV: cross-device link not permitted, rename '/tmp/ on Ubuntu 16.04 LTS

20.5k Views Asked by At

I have problem upload file nodejs. i have read stack1 and stack2. but i think this different case on terminal output like this :

> Unhandled rejection Error: EXDEV: cross-device link not permitted,
> rename '/tmp/31941-53enly.png' ->
> 'public/files/complaint/Screenshot_2016-05-01_01-16-55.png'
>     at Error (native)
>     at Object.fs.renameSync (fs.js:681:18)
>     at null.<anonymous> (/home/faris/myprojects/orchestrale-server/routes/complaintimage.js:163:20)
>     at tryCatcher (/home/faris/myprojects/orchestrale-server/node_modules/sequelize/node_modules/bluebird/js/release/util.js:16:23)
>     at Promise._settlePromiseFromHandler (/home/faris/myprojects/orchestrale-server/node_modules/sequelize/node_modules/bluebird/js/release/promise.js:502:31)
>     at Promise._settlePromise (/home/faris/myprojects/orchestrale-server/node_modules/sequelize/node_modules/bluebird/js/release/promise.js:559:18)
>     at Promise._settlePromise0 (/home/faris/myprojects/orchestrale-server/node_modules/sequelize/node_modules/bluebird/js/release/promise.js:604:10)
>     at Promise._settlePromises (/home/faris/myprojects/orchestrale-server/node_modules/sequelize/node_modules/bluebird/js/release/promise.js:683:18)
>     at Async._drainQueue (/home/faris/myprojects/orchestrale-server/node_modules/sequelize/node_modules/bluebird/js/release/async.js:138:16)
>     at Async._drainQueues (/home/faris/myprojects/orchestrale-server/node_modules/sequelize/node_modules/bluebird/js/release/async.js:148:10)
>     at Immediate.Async.drainQueues [as _onImmediate] (/home/faris/myprojects/orchestrale-server/node_modules/sequelize/node_modules/bluebird/js/release/async.js:17:14)
>     at processImmediate [as _immediateCallback] (timers.js:383:17)

my code :

  if (_.isEmpty(req.files) == false) {
      var tp = avatar_folder+req.files.file.name;
      fs.renameSync(req.files.file.path, tp, function(err){});
      var avatar = req.files.file.name;
      }

code work on another distro like elementary os, but when i run project on debian jessie or ubuntu 16 LTS that error result on terminal.

any body can't help ? that code just run perfectly on elementary os and arch.

11

There are 11 best solutions below

0
On

In order to resolve this problem, you can rewrite as:

fs.writeFile(path_where_to_write, file, function(err) {
    if (err) throw err; /*do something else.*/
});
/*and then Remove the file from tmp location*/
fs.unlink(tempPath);

and for multiple files, you could iterate this block based on length of files.

2
On

Same problem. Workaround: Read the temp file, write the file in new location and remove the temp file:

        // Read the file
        fs.readFile(oldpath, function (err, data) {
            if (err) throw err;
            console.log('File read!');

            // Write the file
            fs.writeFile(newpath, data, function (err) {
                if (err) throw err;
                res.write('File uploaded and moved!');
                res.end();
                console.log('File written!');
            });

            // Delete the file
            fs.unlink(oldpath, function (err) {
                if (err) throw err;
                console.log('File deleted!');
            });
        });
0
On

This issue occurs when your temp folder is in a different drive and Node code is in a different drive.

It will throw this error.

Solution is in another StackOverflow question .

What does the "EXDEV: cross-device link not permitted" error mean?

solution from this post :

As per the new NodeJS, the solution is don`t move, copy it

fs.copyFileSync(oldpath, newpath);
fs.unlink(oldpath,()=>{});

My windows 11 is in SSD and my Codes are in HDD. The uploaded image will be downloaded in windows drive and I am trying to move it to HDD.

1
On
var http = require('http');
var formidable = require('formidable');
var fs = require('fs');

http.createServer(function (req, res) {
if (req.url == '/fileupload') {
var form = new formidable.IncomingForm();
form.parse(req, function (err, fields, files) {
var oldpath = files.filetoupload.path;
console.log(oldpath);
var newpath = 'F:/your folder name/' + files.filetoupload.name;
fs.readFile(oldpath, function (err, data) {
if (err) throw err;
console.log('File read!');

// Write the file
fs.writeFile(newpath, data, function (err) {
if (err) throw err;
res.write('File uploaded and moved!');
res.end();
console.log('File written!');
});

// Delete the file
fs.unlink(oldpath, function (err) {
if (err) throw err;
console.log('File deleted!');
});
});
});
} else {
res.writeHead(200, {'Content-Type': 'text/html'});
res.write('<form action="fileupload" method="post" enctype="multipart/form- 
data">');
res.write('<input type="file" name="filetoupload"><br>');
res.write('<input type="submit">');
res.write('</form>');
return res.end();
}
}).listen(8080);
0
On

In my case, Its working within same disc(drive) path means within c:/ , Error occurred if new path disk drive is different from temp path disk drive.

0
On

You have to use fs.writeFileSync otherwise oldfile can be deleted before copied

fs.writeFileSync(newpath, data, function (err) {
    if (err) throw err;
    res.write('File uploaded and moved!');
    res.end();
    console.log('File written!');
});

// Delete the file
fs.unlink(oldpath, function (err) {
    if (err) throw err;
    console.log('File deleted!');
});
0
On
var http = require('http');
var formidable = require('formidable');
var fs = require('fs');
var mv = require('mv');

http.createServer(function (req, res) {
  if (req.url == '/fileupload') {
    var form = new formidable.IncomingForm();
    form.parse(req, function (err, fields, files) {
      var oldpath = files.filetoupload.path;
     console.log(oldpath);
      var newpath = 'F:/change path to your project dir/' + files.filetoupload.name;
      mv(oldpath, newpath, function (err) {
        if (err) throw err;
        res.write('File uploaded and moved!');
        res.end();
      });
 });
  } else {
    res.writeHead(200, {'Content-Type': 'text/html'});
    res.write('<form action="fileupload" method="post" enctype="multipart/form-data">');
    res.write('<input type="file" name="filetoupload"><br>');
    res.write('<input type="submit">');
    res.write('</form>');
    return res.end();
  }enter code here
}).listen(8080); 
0
On

yes, you can resole this problem as.

  1. install mv by command

    npm install mv --save
    
  2. add mv in your nodejs file

    var mv = require('mv');
    
  3. move file as:

    mv('source_file', 'destination_file,' function(err) {
        if (err) { throw err; }
    console.log('file moved successfully');
    };
    
0
On

I was facing the same error when using docker volumes.

The previous solutions did not work for me as I had to edit the framework I used, namely adminjs, and its upload-feature.

I wanted to store images in the local storage (images folder), while the app was running in a docker container.

I just created a directory called tmp inside my local storage inside that images folder, and added TMP, TEMP, TMPDIR and TEMPDIR environment variables with value of the created tmp folder. Value looks like this: "/app/images/tmp"

The docker run command I used: docker run --name my-app -v /home/user/images:/app/images

Hope, this works for the others as well.

1
On

You can use 'mv' packgage to resolve this issue Link NPM: https://www.npmjs.com/package/mv How to use:

Replace some old code with fs.rename:

    fs.rename(temp_path, target_path, (err) => {
        if (err) {
            console.log('> FileServer.jsx | route: "/files/upload" | err:', err);
            throw err;
        }
    });

With:

    const mv = require('mv');
    mv(temp_path, target_path, function (err) {
        if (err) {
            console.log('> FileServer.jsx | route: "/files/upload" | err:', err);
            throw err;
        }
    });
1
On

it assisted me when working with nodejs , the concept should be the same https://stackoverflow.com/a/43206506/7878987