question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Stream Closed/unexpected end of stream/ Connection reset in post request

See original GitHub issue

My PC settings

  • Processor: intel core i3 8100.
  • gpu: Nvidia geforce gtx 1050 3gb.
  • 8gb ram
  • Windows 10 PRO Version 1909

Versions of installed libraries

"dependencies": {
    "@react-native-community/async-storage": "^1.11.0",
    "@react-native-community/datetimepicker": "^2.6.0",
    "@react-native-community/geolocation": "^2.0.2",
    "@react-native-community/masked-view": "^0.1.10",
    "@react-navigation/bottom-tabs": "^5.6.1",
    "@react-navigation/material-top-tabs": "^5.2.12",
    "@react-navigation/native": "^5.4.3",
    "@react-navigation/stack": "^5.4.0",
    "axios": "^0.19.2",
    "babel-plugin-root-import": "^6.5.0",
    "eslint-config-airbnb": "^18.2.0",
    "eslint-plugin-import": "^2.21.2",
    "eslint-plugin-jsx-a11y": "^6.3.0",
    "eslint-plugin-react": "^7.20.0",
    "eslint-plugin-react-hooks": "^4",
    "immer": "3.1.3",
    "indicative": "^7.4.4",
    "prop-types": "^15.7.2",
    "react": "16.11.0",
    "react-native": "0.62.2",
    "react-native-elements": "^2.0.4",
    "react-native-fs": "^2.16.6",
    "react-native-geocoding": "^0.4.0",
    "react-native-gesture-handler": "^1.6.1",
    "react-native-google-places-autocomplete": "^1.7.2",
    "react-native-hide-with-keyboard": "^1.2.1",
    "react-native-image-picker": "^2.3.3",
    "react-native-linear-gradient": "^2.5.6",
    "react-native-modal": "^11.5.6",
    "react-native-reanimated": "^1.9.0",
    "react-native-redux": "^1.0.10",
    "react-native-safe-area-context": "^2.0.3",
    "react-native-screens": "^2.8.0",
    "react-native-splash-screen": "^3.2.0",
    "react-native-tab-view": "^2.14.4",
    "react-native-vector-icons": "6.6.0",
    "react-navigation": "^4.3.9",
    "react-navigation-tabs": "^2.8.13",
    "react-redux": "7.1.0",
    "reactotron-react-native": "^5.0.0",
    "reactotron-redux": "3.1.1",
    "reactotron-redux-saga": "4.2.2",
    "redux": "4.0.4",
    "redux-persist": "^6.0.0",
    "redux-saga": "1.0.5",
    "rn-fetch-blob": "^0.12.0",
    "styled-components": "^5.1.1"
  },

android/app/src/debug/AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />

<application android:usesCleartextTraffic="true" tools:targetApi="28" tools:ignore="GoogleAppIndexingWarning" />
</manifest>

android/app/src/main/AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.mobile">

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />



<application
  android:name=".MainApplication"
  android:label="@string/app_name"
  android:icon="@mipmap/ic_launcher"
  android:roundIcon="@mipmap/ic_launcher_round"
  android:allowBackup="false"
  android:theme="@style/AppTheme">
  <activity
    android:name=".MainActivity"
    android:label="@string/app_name"
    android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
    android:launchMode="singleTask"
    android:windowSoftInputMode="adjustResize">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
  </activity>
  <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
</application>
</manifest>

android/app/src/main/java/com/mobile/MainActivity.java

package com.mobile;

import com.facebook.react.ReactActivity;

import com.facebook.react.ReactActivityDelegate;
import com.facebook.react.ReactRootView;
import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;

import java.util.List;
import java.util.Arrays;
import com.facebook.react.shell.MainReactPackage;
import com.facebook.react.ReactPackage;

import com.rnfs.RNFSPackage;

public class MainActivity extends ReactActivity {

  /**
   * Returns the name of the main component registered from JavaScript. This is used to schedule
   * rendering of the component.
   */
  
  @Override
  protected String getMainComponentName() {
    return "mobile";
  }

  @Override
  protected ReactActivityDelegate createReactActivityDelegate() {
    return new ReactActivityDelegate(this, getMainComponentName()) {
      @Override
      protected ReactRootView createRootView() {
       return new RNGestureHandlerEnabledRootView(MainActivity.this);
      }
    };
  }
}

android/app/src/main/java/com/mobile/MainAplication.java

package com.mobile;

import android.app.Application;
import android.content.Context;
import com.facebook.react.PackageList;
import com.facebook.react.ReactApplication;
import com.RNFetchBlob.RNFetchBlobPackage;
import com.RNFetchBlob.RNFetchBlobPackage;
import com.rnfs.RNFSPackage;
import com.imagepicker.ImagePickerPackage;
import com.imagepicker.ImagePickerPackage;
import com.swmansion.gesturehandler.react.RNGestureHandlerPackage;
import com.BV.LinearGradient.LinearGradientPackage;
import com.BV.LinearGradient.LinearGradientPackage;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.soloader.SoLoader;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import com.oblador.vectoricons.VectorIconsPackage;

import com.rnfs.RNFSPackage;

import java.util.List;
import java.util.Arrays;
import com.facebook.react.shell.MainReactPackage;
import com.facebook.react.ReactPackage;

public class MainApplication extends Application implements ReactApplication {

  private final ReactNativeHost mReactNativeHost =
      new ReactNativeHost(this) {
        @Override
        public boolean getUseDeveloperSupport() {
          return BuildConfig.DEBUG;
        }

        @Override
        protected List<ReactPackage> getPackages() {
          @SuppressWarnings("UnnecessaryLocalVariable")
          List<ReactPackage> packages = new PackageList(this).getPackages();

          // Packages that cannot be autolinked yet can be added manually here, for example:
          // packages.add(new MyReactNativePackage());
          return packages;
        }

        @Override
        protected String getJSMainModuleName() {
          return "index";
        }
      };

  @Override
  public ReactNativeHost getReactNativeHost() {
    return mReactNativeHost;
  }


  @Override
  public void onCreate() {
    super.onCreate();
    SoLoader.init(this, /* native exopackage */ false);
    initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
  }

  /**
   * Loads Flipper in React Native templates. Call this in the onCreate method with something like
   * initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
   *
   * @param context
   * @param reactInstanceManager
   */
  private static void initializeFlipper(
      Context context, ReactInstanceManager reactInstanceManager) {
    if (BuildConfig.DEBUG) {
      try {
        /*
         We use reflection here to pick up the class that initializes Flipper,
        since Flipper library is not available in release mode
        */
        Class<?> aClass = Class.forName("com.mobile.ReactNativeFlipper");
        aClass
            .getMethod("initializeFlipper", Context.class, ReactInstanceManager.class)
            .invoke(null, context, reactInstanceManager);
      } catch (ClassNotFoundException e) {
        e.printStackTrace();
      } catch (NoSuchMethodException e) {
        e.printStackTrace();
      } catch (IllegalAccessException e) {
        e.printStackTrace();
      } catch (InvocationTargetException e) {
        e.printStackTrace();
      }
    }
  }
}

Code

  • Backend: i’m using multer store locally the image, it works properly.
import multer from 'multer';
import crypto from 'crypto';
import { extname, resolve } from 'path';

export default  {
    storage: multer.diskStorage({ 
        destination: resolve(__dirname, '..', '..', 'temp', 'uploads' ),
        filename: ( req, file, cb ) => {
            crypto.randomBytes(8, ( err, res ) => {
                if ( err ) return cb(err);

                return cb( null, res.toString( 'hex' ) + extname(file.originalname));
            } )
        },
    })
};
  • In routes.js I read the file uploaded at the client.
routes.post('/files', userAuth , upload.single('file'), FileController.store);
  • in the FileController I store the path and the name in my database, working either.
 async store( req, res ) {
       const { filename: path, originalname: name } =  req.file;
                

        const file = await File.create({
            name,
            path
        })
        
        const user = await User.update( {avatar_id: file.toJSON().id}, {where: {id: req.userId}} );


        return res.json(file);
    }

React Native Code

I have a function to store the image.

const storeImage = async (response) => {
    console.log(response);

    RNFetchBlob.config({
      trusty: true,
      timeout: 1000,
    })
      .fetch(
        'POST',
        url,
        {
          'Content-Type': 'multipart/form-data',
          authorization: `Bearer ${token}`,
        },
        [
          {
            name: 'file',
            filename: response.fileName,
            type: response.type,
            data: RNFetchBlob.wrap(response.uri),
          },
        ]
      )
      .then((res) => {
        console.tron.log(res);
      })
      .catch((err) => {
        console.tron.log(err);
      });
  };

And I have a function to call the image picker, and the function to send the image

const showImagePicker = () => {
      console.log(avatarSource);
      console.log(oldAvatarSource);

      ImagePicker.showImagePicker(options, (response) => {
        if (response.didCancel) {
          return null;
        }
        if (response.error) {
          Alert.alert(
            'Erro!',
            'Não consegui recuperar a imagem, tente novamente!'
          );
        } else {
          const source = { uri: response.uri };
          console.log(response); //returns the correct object, with all information
          setAvatarProperties(response);
          setAvatarSource(source);

          /*= ===============SEND IMAGE TO BACKEND================== */
         storeImage (response);
          
        }
      });
    }

What I'm facing

I'm making POST request with RNFetchBlob to my API in backend with nodejs, sometimes it works, sometimes it don't. Sometimes when I upload the image, it is sent to backend fine. But most of the times if I repeat this process without reloading the app, the backend returns me the error:
(node:14568) UnhandledPromiseRejectionWarning: TypeError: Cannot destructure property 'filename' of '(intermediate value)' as it is undefined.
    at update (C:\Users\roble\Documents\programming\apps\embaixada-do-bem-api\src\app\controllers\FileController.js:41:27)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
(node:14568) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:14568) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code. 
And the image is not read by backend until I reload the app and make the request again.

And at the browser(debug mode), I receive the Message some seconds after:

Error: unexpected end of stream
    at VM4 index.bundle:154683
    at MessageQueue.__invokeCallback (VM4 index.bundle:5652)
    at VM4 index.bundle:5356
    at MessageQueue.__guard (VM4 index.bundle:5564)
    at MessageQueue.invokeCallbackAndReturnFlushedQueue (VM4 index.bundle:5355)
    at VM3 debuggerWorker.cff11639.js:4

And in my phone, I receive the messages:

WhatsApp Image 2020-07-19 at 15 45 10

WhatsApp Image 2020-07-19 at 16 06 39

How can I solve that?

I already seen the issue

unexpected end of stream (#419)
and
unexpected end of stream (#399) 
. Did everything i found on the web to solve it, but nothing could.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:1
  • Comments:12

github_iconTop GitHub Comments

10reactions
Mukthayar1commented, Apr 22, 2022

@trsp400 hi, did you solve the unexpected end of stream error?

Yes just upgrade you FLIPPER_VERSION=0.52.1 under android/app/gradlew.properties

0reactions
Mukthayar1commented, May 16, 2022

Thx @Mukthayar1, changing the FLIPPER_VERSION to 0.52.1 really works!

Thanks

Read more comments on GitHub >

github_iconTop Results From Across the Web

java.io.IOException: unexpected end of stream on Connection ...
Its a server error. It means somehow execution returns to your client without the server sending actual response header.
Read more >
How does java net SocketException Connection reset happen
Most common issue for this problem occurring is when you close the socket, and then write more data on the output stream. By...
Read more >
How to Fix with java.net.SocketException: Connection reset ...
This occurs when the Server is reading data and blocked on a read() call but the client was terminated, this time you saw...
Read more >
4.7. The Mysteries of Connection Close - HTTP - O'Reilly
When a connection closes after some request data was sent but before the response is returned, the client cannot be 100% sure how...
Read more >
How to resolve java.net.SocketException: Connection reset
This SocketException occurs on the server side when the client closed the socket connection before the response could be returned over the socket....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found