Got: Doesn't catch `body` (Stream) errors

Created on 20 Sep 2019  路  10Comments  路  Source: sindresorhus/got

How do I prevent my app from crashing when posting a stream to an offline destination? In both examples below I get:

internal/streams/legacy.js:59
      throw er; // Unhandled stream error in pipe.
      ^

Error: connect ECONNREFUSED 127.0.0.1:2024
    at TCPConnectWrap.afterConnect

(I'm on node v12.1.0)

import FormData from 'form-data';
import got from 'got';
import fs from 'fs';

(async () => {
  try {
    const form = new FormData();
    form.append('upload', fs.createReadStream('filepath.jpg'));
    await got.post('http://offlinesite123.com', {
      body: form,
    });
  } catch (err) {
    console.error('does not catch', err);
  }
})();

this also crashes my app

try {
  const form = new FormData();
  form.append('upload', fs.createReadStream('filepath.jpg'));
  got.stream
    .post('http://offlinesite123.com', {
      body: form,
    })
    .on('error', err => console.error('this error gets reported but app still crashes'));
} catch (err) {
  console.error('does not catch', err);
}

Checklist

  • [x] I have read the documentation.
bug external

Most helpful comment

I switched to use stream.pipeline in https://github.com/sindresorhus/got/commit/633651fb711dac21dfd573fbbd25d77968679aa3, but we still need a regression test before closing this. A PR for that would be very welcome.

All 10 comments

I've just experienced this exact same problem, with got 9.6. Downgrading to 8.3 was a viable workaround, but obviously isn't a permanent fix.

I switched to use stream.pipeline in https://github.com/sindresorhus/got/commit/633651fb711dac21dfd573fbbd25d77968679aa3, but we still need a regression test before closing this. A PR for that would be very welcome.

Sorry, I failed to understand why is this closed? The ENOTFOUND or ECONNREFUSED errors are still not handled by catch() and crash the app when destination is offline.

This can be seen in the same snippet as above by @szmarczak (I just updated got to 11.6.0): https://runkit.com/pavek/5f56eeff9e4e8c001a3984c4

Is there a workaround that I miss in the docs?

@szmarczak Thanks for reopening. I guess it will be fixed in the next release?

I found a workaround using got streams API that, unlike promises in current version, correctly handles errors during upload. One particularly tricky part was to get response body after upload - sharing it here for it's not documented elsewhere:

const uploadFile = async (filePath, url, onProgress) => {
    let error = null, json = null, response = null;

    try {
        const formData = new FormData();
        formData.append('image', fs.createReadStream(filePath));

        response = await new Promise((resolve, reject) => {
            got
                .post(url, {
                    body: formData,
                    isStream: true, // Use `got` streaming API as promises do not handle errors correctly in 11.6.0
                })
                .on('uploadProgress', onProgress)
                .on('response', resolve)
                .on('error', reject);
        });

        // Consume response body. Async Iterator works unlike `response.on('data')`
        let data = '';
        for await (const chunk of response) {
            data += chunk;
        }

        json = JSON.parse(data);
    }
    catch (e) {
        error = e;
    }

    return { error, json, response };
};

This is possibly a Node.js bug. Investigating more.

@szmarczak are there any updates on this one?

It's fixed via a Node.js update. Just checked the latest one, works as expected.

Was this page helpful?
0 / 5 - 0 ratings