node-formidable / formidable

The most used, flexible, fast and streaming parser for multipart form data. Supports uploading to serverless environments, AWS S3, Azure, GCP or the filesystem. Used in production.
MIT License
7.06k stars 682 forks source link

Why I got TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received null #668

Closed Navid61 closed 3 years ago

Navid61 commented 3 years ago

Support plan

Context

What are you trying to achieve or the steps to reproduce?

When I try to upload my files to the server I get this error. My code on localhost works without problem, but when I run the code on the server I get this error. I want my files after upload to be on my favorite path on the server.

spawn("sudo", ["mkdir", `${tempTrim}`])
spawn("sudo", ["chown", "-R", "sigma:sigma", `${tempTrim}`])

var form = formidable({ multiples: true, maxFileSize: 700 * 1024 * 1024, keepExtensions: true});

form.on('progress', function (bytesReceived, bytesExpected) {
    console.log('PROGRESS');
    console.log(bytesReceived);
    console.log(bytesExpected);
});

form.once('error', console.error)

 form.on('fileBegin', function(name, file) {

     file.path = `${tempTrim}/${file.name}`

   })

        form.on('file', (filename, file) => {
            form.emit('data', { name: 'file', key: filename, value: file });
        });

        form.on('field', (fieldName, fieldValue) => {
            form.emit('data', { name: 'field', key: fieldName, value: fieldValue });
        });

        form.once('end', async() => {
            console.log('Done!');
         await zipShapeFiles()

        });

        form.parse(req, (err, fields, files) => {
            if (err) {
                console.error('Error', err)
                next(err)
                return

            }

What was the result you got?

TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received null
    at new NodeError (node:internal/errors:278:15)
    at validateString (node:internal/validators:123:11)
    at Object.extname (node:path:1273:5)
    at IncomingForm._uploadPath (/home/sigma/sigmamap/node_modules/formidable/src/Formidable.js:440:22)
    at IncomingForm._handlePart (/home/sigma/sigmamap/node_modules/formidable/src/Formidable.js:288:18)
    at IncomingForm.onPart (/home/sigma/sigmamap/node_modules/formidable/src/Formidable.js:241:10)
    at MultipartParser.<anonymous> (/home/sigma/sigmamap/node_modules/formidable/src/plugins/multipart.js:147:14)
    at MultipartParser.emit (node:events:376:20)
    at MultipartParser.EventEmitter.emit (node:domain:470:12)
    at addChunk (node:internal/streams/readable:305:12)
    at readableAddChunk (node:internal/streams/readable:280:9)
    at MultipartParser.Readable.push (node:internal/streams/readable:219:10)
    at MultipartParser._handleCallback (/home/sigma/sigmamap/node_modules/formidable/src/parsers/Multipart.js:95:10)
    at MultipartParser._transform (/home/sigma/sigmamap/node_modules/formidable/src/parsers/Multipart.js:228:16)
    at MultipartParser.Transform._write (node:internal/streams/transform:184:23)
    at writeOrBuffer (node:internal/streams/writable:388:12) {
  code: 'ERR_INVALID_ARG_TYPE'
}
Error TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received null
    at new NodeError (node:internal/errors:278:15)
    at validateString (node:internal/validators:123:11)
    at Object.extname (node:path:1273:5)
    at IncomingForm._uploadPath (/home/sigma/sigmamap/node_modules/formidable/src/Formidable.js:440:22)
    at IncomingForm._handlePart (/home/sigma/sigmamap/node_modules/formidable/src/Formidable.js:288:18)
    at IncomingForm.onPart (/home/sigma/sigmamap/node_modules/formidable/src/Formidable.js:241:10)
    at MultipartParser.<anonymous> (/home/sigma/sigmamap/node_modules/formidable/src/plugins/multipart.js:147:14)
    at MultipartParser.emit (node:events:376:20)
    at MultipartParser.EventEmitter.emit (node:domain:470:12)
    at addChunk (node:internal/streams/readable:305:12)
    at readableAddChunk (node:internal/streams/readable:280:9)
    at MultipartParser.Readable.push (node:internal/streams/readable:219:10)
    at MultipartParser._handleCallback (/home/sigma/sigmamap/node_modules/formidable/src/parsers/Multipart.js:95:10)
    at MultipartParser._transform (/home/sigma/sigmamap/node_modules/formidable/src/parsers/Multipart.js:228:16)
    at MultipartParser.Transform._write (node:internal/streams/transform:184:23)
    at writeOrBuffer (node:internal/streams/writable:388:12) {
  code: 'ERR_INVALID_ARG_TYPE'
}
TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received null
    at new NodeError (node:internal/errors:278:15)
    at validateString (node:internal/validators:123:11)
    at Object.extname (node:path:1273:5)
    at IncomingForm._uploadPath (/home/sigma/sigmamap/node_modules/formidable/src/Formidable.js:440:22)
    at IncomingForm._handlePart (/home/sigma/sigmamap/node_modules/formidable/src/Formidable.js:288:18)
    at IncomingForm.onPart (/home/sigma/sigmamap/node_modules/formidable/src/Formidable.js:241:10)
    at MultipartParser.<anonymous> (/home/sigma/sigmamap/node_modules/formidable/src/plugins/multipart.js:147:14)
    at MultipartParser.emit (node:events:376:20)
    at MultipartParser.EventEmitter.emit (node:domain:470:12)
    at addChunk (node:internal/streams/readable:305:12)
    at readableAddChunk (node:internal/streams/readable:280:9)
    at MultipartParser.Readable.push (node:internal/streams/readable:219:10)
    at MultipartParser._handleCallback (/home/sigma/sigmamap/node_modules/formidable/src/parsers/Multipart.js:95:10)
    at MultipartParser._transform (/home/sigma/sigmamap/node_modules/formidable/src/parsers/Multipart.js:228:16)
    at MultipartParser.Transform._write (node:internal/streams/transform:184:23)
    at writeOrBuffer (node:internal/streams/writable:388:12)

What result did you expect ?

I'd expect my files to transfer to my favorite path on my server and the upload process to complete without any empty file or incomplete file.

GrosSacASac commented 3 years ago

If it works locally, maybe you have done something else on the server that causes this error.

Also try to update your formidable version.

Navid61 commented 3 years ago

Thank you for your answer, I thought my code has problem, if you seen that and you didn't find any mistake, I'll check server confing, but sometimes this happen when I add keep Extensions: true

Navid61 commented 3 years ago

If I put formidable extension like below:

cost firm = formidable ({multiple: true, uploadDir: '/tmp', keepExtensions: true})

I will get that error message I added above already but if I use this method:

form.keepExtemsions = true form.uploadDir = '/tmp'

I did not get error message again, I checked formidable version I've been using latest version, I didn't find any special config or specific change on my server, moreover tmp folder permission is 777

tunnckoCore commented 3 years ago

but if I use this method

Because this method does nothing in v2 anymore, so it should proceed with the defaults.

Just for confirmation, are you installing the canary, or from git master branch?

And, any reason why you explicitly define uploadDir: '/tmp'? I'm pretty sure we does that by default.

Navid61 commented 3 years ago

Thank for your answer, yes I did install formidable canary.

Which form is not correct for v2 form.keepExtemsions or put options inside formidable? is there any way to define a specific port number for formidable? Because I know tmp folder has full read write execute (rwx) permission by default, Hence I'd expect my files transfer to this folder without any error but when I got this error tmp folder will be empty, based on error which path is mean of formidable, tmp path, path on client side, path defined by beginPath, I can't understand what path I should look or do research about that

tunnckoCore commented 3 years ago

Passing to the options is the correct way. And there's a note for this. Using a constructor isn't recommended too.

is there any way to define a specific port number for formidable?

We does nothing with ports. You pass a port to the server, so...

Navid61 commented 3 years ago

Very well thank you so much, I think this error we are discussing about here, that would be relate to "file.path" , I can see some parts of my files will be upload but suddenly I'll get "path" error during upload process, formidable will crash because it got null, I don't know why during upload precedure program will get null, I'm pretty sure my files are heath and I did not upload any empty file, this will happen when I want upload file via laptop(client) to server, by the way if there is an option or any method can handle this sort of error such as null ( I don't know why suddenly formidable will get null among files! ) let me know, I put my code in try catch but it couldn't do any help. Thank in advance

tunnckoCore commented 3 years ago

I don't know why during upload precedure program will get null

The thing is that we "analyze" the incoming files - like, getting the file extension, renaming, sanitizing and etc, and that's why. Unfortunately, it's possible that this may fail through this process...

Does your file has extension? Can you just share the name of the file? What I'm seeing now is that probably part.filename is empty for some reason, thus passes non valid thing to the path.* methods used in _getExtension.

Can you debug a bit for us?

around 498 line

// src/Formidable.js file

    if (part && this.options.keepExtensions) {
      const filename = typeof part === 'string' ? part : part.filename;
      // console.log('keepExts', filename)
      return `${name}${this._getExtension(filename)}`;
    }

and around 480 line

  _getExtension(str) {
    // console.log('getExt str:', str)
    const basename = path.basename(str);
    // console.log('basename:', basename)
    const firstDot = basename.indexOf('.');
    const lastDot = basename.lastIndexOf('.');
    const extname = path.extname(basename).replace(/(\.[a-z0-9]+).*/i, '$1');

    if (firstDot === lastDot) {
      return extname;
    }

    return basename.slice(firstDot, lastDot) + extname;
  }
Navid61 commented 3 years ago

Before everything I really appreciate for your answer, I think my issued fixed Yes my file has extension, I uninstalled formidable@canary and reinstalled again for I'll be sure my installation is clean. This is my debug result: keepExts asphalt-road1-line.dbf getExt str: asphalt-road1-line.dbf basename: asphalt-road1-line.dbf keepExts asphalt-road1-line.sbn getExt str: asphalt-road1-line.sbn basename: asphalt-road1-line.sbn keepExts asphalt-road1-line.sbx getExt str: asphalt-road1-line.sbx basename: asphalt-road1-line.sbx keepExts asphalt-road1-line.shp getExt str: asphalt-road1-line.shp basename: asphalt-road1-line.shp Error Error: Request aborted at IncomingMessage. (/home/sigma/sigmamap/node_modules/formidable/src/Formidable.js:184:21) at IncomingMessage.emit (node:events:376:20) at IncomingMessage.EventEmitter.emit (node:domain:470:12) at abortIncoming (node:_http_server:581:9) at socketOnClose (node:_http_server:572:3) at Socket.emit (node:events:388:22) at Socket.EventEmitter.emit (node:domain:470:12) at TCP. (node:net:666:12) Error: Request aborted at IncomingMessage. (/home/sigma/sigmamap/node_modules/formidable/src/Formidable.js:184:21) at IncomingMessage.emit (node:events:376:20) at IncomingMessage.EventEmitter.emit (node:domain:470:12) at abortIncoming (node:_http_server:581:9) at socketOnClose (node:_http_server:572:3) at Socket.emit (node:events:388:22) at Socket.EventEmitter.emit (node:domain:470:12) at TCP. (node:net:666:12) This will happen when I was trying to upload files by fetch api but when I did upload by

tag it seems it could sent my files, However I should check again size of my uploaded file on client and server if size of file is equal with origin my upload problem is fixed completely.I think there will be no any problem. Thank so much

tunnckoCore commented 3 years ago

You're now getting Request aborted error. Hm.

Try using formidable-serverless, it will be integrated in v2 soon with #594

Navid61 commented 3 years ago

Bunch of thanks🙏, my problem solved, I'm using html tag <form action="" method="post" enctype=enctype='multipart/form-data'> instead of fetch API and know I can upload without any error, at least not yet ;), If I encounter dilemma again such as Abort... Or path error I'll write here. However It seems I can launch my project the day after tomorrow without any stress and problem