electron-userland / electron-builder

A complete solution to package and build a ready for distribution Electron app with “auto update” support out of the box
https://www.electron.build
MIT License
13.61k stars 1.74k forks source link

cannot catch errors like net::ERR_NETWORK_CHANGED, net::ERR_CONNECTION_RESET #2398

Closed hvuntokrul closed 5 years ago

hvuntokrul commented 6 years ago

description of what you're trying to do: I am trying to catch errors like: net::ERR_NETWORK_CHANGED, net::ERR_CONNECTION_RESET, net::ERR_SPDY_PROTOCOL_ERROR, net::ERR_CONNECTION_CLOSED etc, but autoUpdater.on('error', errorHandler); (import { autoUpdater } from 'electron-updater';) does not catch them and errors go straight to process.on(‘uncaughtException’, handleUncaught). Most errors occur when the internet connection is lost while downloading an update.

package.json:

{
"name": "electron-react-boilerplate",
"productName": "ElectronReact",
"version": "0.10.0",
"description": "Electron application boilerplate based on React, React Router, Webpack, React Hot Loader for rapid application development",
"main": "main.js",
"scripts": {
"hot-updates-server": "cross-env NODE_ENV=development node --trace-warnings -r babel-register ./node_modules/webpack-dev-server/bin/webpack-dev-server --config webpack.config.renderer.dev.js",
"build": "concurrently \"npm run build-main\" \"npm run build-renderer\"",
"build-dll": "cross-env NODE_ENV=development node --trace-warnings -r babel-register ./node_modules/webpack/bin/webpack --config webpack.config.renderer.dev.dll.js --progress --profile --colors",
"build-main": "cross-env NODE_ENV=production node --trace-warnings -r babel-register ./node_modules/webpack/bin/webpack --config webpack.config.main.prod.js --progress --profile --colors",
"build-renderer": "cross-env NODE_ENV=production node --trace-warnings -r babel-register ./node_modules/webpack/bin/webpack --config webpack.config.renderer.prod.js --progress --profile --colors",
"start": "cross-env NODE_ENV=production electron ./app/",
"start-hot-renderer": "cross-env HOT=1 NODE_ENV=development electron -r babel-register -r babel-polyfill ./app/main.development",
"postinstall": "concurrently \"npm run build-dll\" \"install-app-deps\" \"node node_modules/fbjs-scripts/node/check-dev-engines.js package.json\"",
"dev": "cross-env START_HOT=1 npm run hot-updates-server",
"package": "npm run build && build --publish never",
"package-win-64": "npm run build && build --win --x64",
"package-win-32": "npm run build && build --win --ia32",
"package-linux": "npm run build && build --linux",
"package-all": "npm run build && build -mwl",
"cleanup": "mop -v"
},
"browserslist": "electron 1.8.1",
"build": {
"productName": "FontBase",
"appId": "com.dominiklevitsky.fontbase",
"asar": true,
"dmg": {
"icon": "installer.icns",
"contents": [
{
"x": 410,
"y": 150,
"type": "link",
"path": "/Applications"
},
{
"x": 130,
"y": 150,
"type": "file"
}
]
},
"nsis": {
"installerIcon": "installer.ico",
"uninstallerIcon": "installer.ico",
"artifactName": "${productName}-${version}.${ext}"
},
"files": [
"node_modules/",
"providers/",
"assets/icons/",
"dist/main.js",
"dist/app.js",
"dist/synchronizer.js",
"dist/activator.js",
"dist/filemanager.js",
"dist/style.css",
"auth0.min.js",
"app.html",
"synchronizer.html",
"activator.html",
"filemanager.html",
"error.html",
"package.json"
],
"win": {
"target": "nsis",
"icon": "resources/icon.ico"
},
"linux": {
"target": [
"deb",
"AppImage"
]
},
"publish": {
"provider": "generic",
"url": "https://releases.fontba.se/${os}/"
},
"directories": {
"buildResources": "resources",
"output": "release"
}
},
"devDependencies": {
"asar": "^0.13.0",
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-plugin-add-module-exports": "^0.2.1",
"babel-plugin-dev-expression": "^0.2.1",
"babel-plugin-dynamic-import-webpack": "^1.0.1",
"babel-plugin-root-import": "^5.1.0",
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-plugin-transform-es2015-classes": "^6.24.1",
"babel-polyfill": "^6.26.0",
"babel-preset-env": "^1.6.0",
"babel-preset-react": "^6.24.1",
"babel-preset-react-hmre": "^1.1.1",
"babel-preset-react-optimize": "^1.0.1",
"babel-preset-stage-0": "^6.24.1",
"babel-register": "^6.26.0",
"brfs": "^1.4.3",
"concurrently": "^3.5.0",
"cross-env": "^5.0.5",
"css-loader": "^0.28.7",
"electron": "^1.8.0",
"electron-builder": "^19.27.7",
"electron-builder-squirrel-windows": "^19.27.3",
"electron-debug": "^1.4.0",
"electron-devtools-installer": "^2.2.0",
"electron-rebuild": "^1.6.0",
"express": "^4.15.4",
"extract-text-webpack-plugin": "^3.0.0",
"fbjs-scripts": "^0.8.1",
"file-loader": "^0.11.2",
"html-webpack-plugin": "^2.30.1",
"if-webpack-plugin": "^1.0.3",
"node-sass": "^4.5.3",
"packageify": "^1.0.0",
"redux-logger": "^3.0.6",
"sass-loader": "^6.0.6",
"string-replace-webpack-plugin": "^0.1.3",
"style-loader": "^0.18.2",
"svg-inline-loader": "^0.8.0",
"transform-loader": "^0.2.4",
"uglifyjs-webpack-plugin": "^1.1.1",
"url-loader": "^0.5.9",
"webpack": "^3.5.5",
"webpack-dev-server": "^2.7.1",
"webpack-merge": "^4.1.0"
},
"dependencies": {
"base-64": "^0.1.0",
"classnames": "^2.2.5",
"electron-updater": "^2.16.3",
"electron-window-state": "^4.1.1",
"file-url": "^2.0.2",
"fontkit": "^1.7.7",
"history": "^4.7.2",
"immutable": "^3.8.1",
"jwt-decode": "^2.2.0",
"localforage": "^1.5.0",
"lodash": "^4.17.4",
"mkdirp": "^0.5.1",
"mousetrap": "^1.6.1",
"rc-slider": "^8.3.1",
"react": "^16.2.0",
"react-color": "^2.13.5",
"react-dnd": "^2.5.4",
"react-dnd-html5-backend": "^2.4.1",
"react-dom": "^16.2.0",
"react-hot-loader": "^3.0.0-beta.6",
"react-onclickoutside": "^6.5.0",
"react-redux": "^5.0.6",
"react-resize-detector": "^1.1.0",
"react-router": "^3.0.5",
"react-router-dom": "^4.1.1",
"react-router-redux": "^4.0.8",
"react-timeout": "^1.0.1",
"react-virtualized": "^9.9.0",
"redux": "^3.7.2",
"redux-persist": "^4.9.1",
"redux-persist-immutable": "^4.3.1",
"redux-thunk": "^2.2.0",
"reselect": "^3.0.1",
"source-map-support": "^0.4.15",
"winston": "^2.3.1"
},
"optionalDependencies": {
"7zip-bin-linux": "^1.1.0",
"7zip-bin-win": "^2.1.1"
},
"devEngines": {
"node": ">=6.x",
"npm": ">=3.x",
"yarn": "0.21.3"
}
}

log of the terminal output:

2017-12-19T10:23:58.455Z – ERROR – net:ERR_CONNECTION_RESET
2017-12-19T11:40:52.112Z – ERROR – net::ERR_NETWORK_CHANGED

node version: 8.4.0

npm version: 5.0.3

on which system do you want to create installers (macOS, Linux or Windows): macOS and Windows

btibarra commented 6 years ago

Same problem here, have you figured out how to solve it?

FantasticFiasco commented 6 years ago

I am experiencing issues with this as well. Do we have any workaround for it?

hvuntokrul commented 6 years ago

@btibarra @FantasticFiasco thanks for replying guys. No reply from package developers for now. As a temporary workaround you can try catching errors with process.on('uncaughtException', callback) in your main process or window.onerror = function yourExceptionHandler(msg, url, line, column, error) {}) in a renderer process. Or with Node's domain api (https://nodejs.org/api/domain.html), but it's supposed to be deprecated soon and replaced with something else. Not sure how soon though so it might be worth a try :) Anyway, hope some of this will help you guys:) Will continue waiting for the devs to reply for now

btibarra commented 6 years ago

Thanks for the reply @hvuntokrul , I will try with one of your suggestions 👍

EtienneLem commented 6 years ago

Sounds like #2451. I’d really love to catch them as well, so they don’t end up in Rollbar (which uses uncaughtException). I’m also getting flooded by other errors like ENOSPC: no space left on device or Cannot update while running on a read-only volume, etc.

I don’t know for sure, but it looks like that might be this: https://github.com/electron-userland/electron-builder/blob/9d6eb9602522048597b185c604f02387820aa8d9/packages/electron-updater/src/AppUpdater.ts#L339-L346

Everywhere in AppUpdater that there’s error handling, it emits the error event and re-throw the original error. Given these are async functions, it looks like catching is not possible. I’m not sure why we’d want to throw an error as well as emit the error event.

DominikLevitsky commented 6 years ago

@develar Where do I need to send money so this can be finally resolved?

develar commented 6 years ago

@DominikLevitsky Donation doesn't mean that issue will be resolved ASAP. No obligations.

If you can provide reproducible steps — it will help.

hvuntokrul commented 6 years ago

@develar The most reliable way to reproduce the issue is to start updating the Electron application while the computer is connected to the internet via a Wi-Fi network and connect to another network while the update is still in progress

mbenarie commented 6 years ago

same here

SlavkoPekaric commented 6 years ago

+1

avner-hoffmann commented 6 years ago

is there a solution cooking for this issue??

dingchaoyan1983 commented 6 years ago

how about this issue ?

meekaah commented 6 years ago

got the same issue :(

tjazak commented 6 years ago

Here's an example of what I got to work for me. I was only able to catch all of them if autoDownload == false.

autoUpdater.autoDownload = false;

function checkForUpdates() {
    autoUpdater.checkForUpdates().then((info) => {
        if (autoUpdater.updateAvailable) {
            downloadUpdate(info.cancellationToken);
        } else {
            log.info('Update not available')
        }
    }).catch((error) => {
        if (isNetworkError(error)) {
            log.info('Network Error');
        } else {
            log.info('Unknown Error');
            log.info(error == null ? "unknown" : (error.stack || error).toString());
        }
    });
}

function downloadUpdate(cancellationToken) {
    autoUpdater.downloadUpdate(cancellationToken).then((file) => {
        setImmediate(() => autoUpdater.quitAndInstall());
    }).catch((error) => {
        if (isNetworkError(error)) {
            log.info('Network Error');
        } else {
            log.info('Unknown Error');
            log.info(error == null ? "unknown" : (error.stack || error).toString());
        }
    });
}

function isNetworkError(errorObject) {
    return errorObject.message === "net::ERR_INTERNET_DISCONNECTED" ||
        errorObject.message === "net::ERR_PROXY_CONNECTION_FAILED" ||
        errorObject.message === "net::ERR_CONNECTION_RESET" ||
        errorObject.message === "net::ERR_CONNECTION_CLOSE" ||
        errorObject.message === "net::ERR_NAME_NOT_RESOLVED" ||
        errorObject.message === "net::ERR_CONNECTION_TIMED_OUT";
}
vladimiry commented 5 years ago

I played around the issue on Windows for about few hours trying different ideas and came up with a simple PR which makes checkForUpdatesAndNotify() call actually catchable.

avner-hoffmann commented 5 years ago

Hi all, I'm facing the same issue while the auto updater tries to download an update, I'm getting 'net:ERR_ABORTED' once the computer is put into sleep while the update is downloaded I understand that currently there's no fix for that

Regarding the above suggestions, even though it's not a best practice according to nodejs docs, how can it be solved using process.on('uncauhghtException', err => ...)? Clearly electron itself catches the uncaught exceptions for us, since when I get this error a native modal pops up that prints the error and the application keeps running. Basically we want to catch and swallow only the relevant errors, but in case another error is caught we'd like to continue the flow as it is, meaning to keep propagating the error to electron's uncaught exception handler that will do whatever it decides to do. How can it be done using that approach? I guess throwing the error from the uncaughtException error handler if error.message isn't our error.message isn't acceptable and won't do the trick? How can it be done ?

avner-hoffmann commented 5 years ago

@tjazak - In what version of auto updater are you using? I don't have any property autoUpdater.updateAvailable and the UpdateCheckResult object that is returned from autoUpdater.checkForUpdates() doesn't have any property saying if an update is available or not. Should I manually check the update version with the current one? The documentation in electron-builder doesn't specify how to use the UpdateCheckResult, it almost looks like they never intended it to be used with promise based approach...

alanning commented 5 years ago

I believe this issue can be closed now that this PR by @vladimiry has been merged and released in electron-updater@4.0.7.

thetroy commented 5 years ago

I still see this issue after forcing the install of 4.0.7 (i.e. 4.0.6 is still considered latest right now).

Traced the issue into httpExecutor added a patch to configurePipes(). The code already listens for error events on each stream, but not on the response. Adding an error listener to the response eliminated the uncaught exception for me.

I only patched configurePipes(), other parts of httpExecutor may also need listeners.

  // PATCH START
  //   Steps to reproduce bug:
  //     start downloading an update
  //     disable wifi for ~10s
  //     enable wifi -- might see some more bytes arrive then stop
  //     wait ~10min
  //       an uncaught networking exception with be thrown
  //       wait times may vary
  //
  //   Fix:
  //     The response is used as a Stream below, so we need to
  //     listen for error events to prevent errors from being
  //     thrown
  //
  //   Notes:
  //     - other parts of this file may need patching too
  //     - it seems, listening for errors on the request is
  //       not enough.
  //     - if the download resumes when you enable wifi, try disabling for longer
  //
  response.on("error", error => {
    if (!options.options.cancellationToken.cancelled) {
      options.callback(error);
    }
  })
  // PATCH END

  for (const stream of streams) {
    stream.on("error", error => {
      if (!options.options.cancellationToken.cancelled) {
        options.callback(error);
      }
    });
    lastStream = lastStream.pipe(stream);
  }

I'm applying the patch using patch-package

Hope this^ info helps others. Happy to whip up a PR if this looks like a legit fix.

--- big thanks to electron-builder !!!

vladimiry commented 5 years ago

I believe this issue can be closed now that this PR by @vladimiry has been merged and released in electron-updater@4.0.7.

By the way, that PR tweaked only checkForUpdatesAndNotify method but I didn't explore the checkForUpdates method which also might potentially be a problematic one.

thetroy commented 5 years ago

I use checkForUpdates and downloadUpdate. I tried switching to checkForUpdatesAndNotify, but was still seeing the uncaught exception, so i reverted and started digging.

I need to amend the patch/comments -- after waiting 10min i didn't see the error, so I enabled wifi again, and saw the error (net::ERR_CONNECTION_RESET). When digging, I would disable / enable wifi (so i could read the docs)...didn't expect the enable was needed to reproduce.

vladimiry commented 5 years ago

@thetroy I can only suggest you make sure you are using the most recent electron-updater version which is currently 4.0.11 and if still fails to try switching to 4.0.7.

stale[bot] commented 5 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

johanneslumpe commented 5 years ago

This really shouldn't be closed because the bug is still happening. What @thetroy posted is spot on. Applying the patch and listening to the error event on the response fixes the issue of an uncaught error during update download, which else will lead to the application just crashing.

kzimny commented 5 years ago

I have the same issue as @johanneslumpe. I get the message ERR_INTERNET_DISCONNECTED and after that the application is crashing. Any idea how to solve/catch it?

lacymorrow commented 4 years ago

Can we reopen this?

lacymorrow commented 4 years ago

Error: net::ERR_NETWORK_IO_SUSPENDED` on computer sleep, the cause could possibly be not explicitly setting a timeout on the http calls.

technicallyty commented 4 years ago

Got this issue as well. Anyone ever have any luck with fixing it? image

kzimny commented 4 years ago

Try v.22.3.1 available as electron-builder@next npm package. There should be a fix for this issue. If it doesn't work check if connection exists before check for update.

VerteDinde commented 4 years ago

Looks like the issue is still unfortunately present as of 22.3.5 - I see the ERR_CONNECTION_RESET if the update process is interrupted or the connection is interrupted during the update, and then restarted

alanning commented 4 years ago

If I'm understanding correctly, this issue should be re-opened since a global error handler is still required to catch certain connection exceptions:

autoUpdater.checkForUpdatesAndNotify().catch(err => {
  console.error('[initApp.checkForUpdates] Update failed: ' + err)
})
process.on('uncaughtException', (err) => {
  console.error('[uncaughtException] Whoops! There was an error: ' + err)
})

It would be very helpful if someone could post a simple repository that reliably generates these errors.

Regarding ERR_CONNECTION_RESET, does anyone know if 22.3.5 contains a fix for configurePipes as @thetroy mentioned above?

VerteDinde commented 4 years ago

@alanning I don't believe 22.3.5 has that patch in it, I don't see a merged PR that contains it (but @thetroy, let me know if I'm wrong!). It would be great to get that in a PR.

I can consistently reproduce the net::ERR_CONNECTION_RESET crash in our application by starting an update download, then turning the internet off for ~30 seconds while the update is downloading - I haven't been able to reproduce the other errors.

VerteDinde commented 4 years ago

Hey folks 👋 Just wanted to update you - I tried applying @thetroy's fix via patch-package over the weekend, but we're unfortunately still seeing the net::ERR_CONNECTION_RESET in our app. @lacymorrow, I also hit the net::ERR_NETWORK_IO_SUSPENDED error that you reported seeing, but haven't been able to reproduce. We have a global error handler catching this, but it still creates a bad experience for the user, and I think it would be ideal to patch it in electron-builder itself, I'll see if I can work on a fix.

Do you all think it would be alright for me to create a new issue in lieu of re-opening this one, since this does seem to still be affecting all of us? Might be helpful for others who are hitting this as well; since Electron 7 refactored the net module, I suspect other folks who upgraded will be seeing more of this error soon.

lincolnthree commented 4 years ago

Still happening here. @VerteDinde did you create a new issue?

lacymorrow commented 4 years ago

@alanning I have a repository that always exhibits the error when a Windows OS sleeps and is unsuspended while the app is running, https://github.com/lacymorrow/crossover.

@VerteDinde A new issue is fine, just link us when you create it 👍

sydney-d commented 4 years ago

Hello,

Still an issue for me too. Anyone found a workaround ?

Thanks

capc0 commented 2 years ago

issue is still present for me with autoUpdater.checkForUpdates()

any updates?

pavelberezhnoy commented 2 years ago

I managed to deal with it this way. I hope it helps somebody.

try {
   const updateCheckResult = await autoUpdater.checkForUpdates();
   if (updateCheckResult.downloadPromise) {
      updateCheckResult.downloadPromise.catch(error => {
         console.error('Error while downloading the update: ', error);
      });
   }
} catch (error) {
   console.error('Error while on checkForUpdates: ', error);
}
louismorgner commented 1 year ago

I also experience this issue still, why is it closed?