Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Updating node.js causes 'write EPIPE' with ng e2e

I have an angular 7 application which runs its e2e tests during a CI pipeline on a server. My server's package manager updated the node.js version from 10.14 to 10.14.2 (Both LTS versions) This causes ng e2e to throw the following error:

i 「wdm」: Compiled successfully.
[13:38:47] I/update - chromedriver: file exists node_modules\webdriver-manager\selenium\chromedriver_2.45.zip
[13:38:47] I/update - chromedriver: unzipping chromedriver_2.45.zip
[13:38:48] I/update - chromedriver: chromedriver_2.45.exe up to date
events.js:167
      throw er; // Unhandled 'error' event
      ^

Error: write EPIPE
    at ChildProcess.target._send (internal/child_process.js:742:20)
    at ChildProcess.target.send (internal/child_process.js:626:19)
    at Observable.rxjs_1.Observable.obs [as _subscribe] (node_modules\@angular-devkit\build-angular\src\utils\run-module-as-observable-fork.js:57:23)
    at Observable._trySubscribe (node_modules\rxjs\internal\Observable.js:44:25)
    at Observable.subscribe (node_modules\rxjs\internal\Observable.js:30:22)
    at node_modules\rxjs\internal\util\subscribeTo.js:22:31
    at Object.subscribeToResult (node_modules\rxjs\internal\util\subscribeToResult.js:10:45)
    at MergeMapSubscriber._innerSub (node_modules\rxjs\internal\operators\mergeMap.js:82:29)
    at MergeMapSubscriber._tryNext (node_modules\rxjs\internal\operators\mergeMap.js:76:14)
    at MergeMapSubscriber._next (node_modules\rxjs\internal\operators\mergeMap.js:59:18)
    at MergeMapSubscriber.Subscriber.next (node_modules\rxjs\internal\Subscriber.js:67:18)
    at MergeMapSubscriber.notifyNext (node_modules\rxjs\internal\operators\mergeMap.js:92:26)
    at InnerSubscriber._next (node_modules\rxjs\internal\InnerSubscriber.js:28:21)
    at InnerSubscriber.Subscriber.next (node_modules\rxjs\internal\Subscriber.js:67:18)
    at node_modules\rxjs\internal\util\subscribeToPromise.js:7:24
    at process._tickCallback (internal/process/next_tick.js:68:7)
Emitted 'error' event at:
    at process.nextTick (internal/child_process.js:746:39)
    at process._tickCallback (internal/process/next_tick.js:61:11)

I was able to reproduce this locally, when i rollback to 10.14 ng e2e works again.

package.json:

"dependencies": {
    "@angular-devkit/build-angular": "~0.10.0",
    "@angular/animations": "^7.0.1",
    "@angular/cdk": "^7.0.2",
    "@angular/common": "^7.0.1",
    "@angular/compiler": "^7.0.1",
    "@angular/core": "^7.0.1",
    "@angular/forms": "^7.0.1",
    "@angular/http": "^7.0.1",
    "@angular/material": "^7.0.2",
    "@angular/platform-browser": "^7.0.1",
    "@angular/platform-browser-dynamic": "^7.0.1",
    "@angular/platform-server": "^7.0.1",
    "@angular/router": "^7.0.1",
    "@ng-bootstrap/ng-bootstrap": "^4.0.0",
    "@ngx-translate/core": "^11.0.0",
    "@ngx-translate/http-loader": "^4.0.0",
    "aspnet-prerendering": "^3.0.1",
    "bootstrap": "^4.1.3",
    "classlist.js": "^1.1.20150312",
    "core-js": "^2.5.7",
    "devextreme": "18.1.4",
    "devextreme-angular": "18.1.4",
    "devextreme-aspnet-data": "1.4.5",
    "lodash": "^4.17.11",
    "node-sass": "^4.10.0",
    "rxjs": "^6.3.3",
    "toastr": "^2.1.4",
    "webpack": "^4.19.1",
    "zone.js": "^0.8.26"
},
    "devDependencies": {
    "@angular-devkit/core": "0.8.3",
    "@angular/cli": "^7.0.3",
    "@angular/compiler-cli": "^7.0.1",
    "@angular/language-service": "^7.0.1",
    "@babel/core": "^7.1.2",
    "@compodoc/compodoc": "^1.1.5",
    "@storybook/addon-actions": "^4.0.0",
    "@storybook/addon-knobs": "^4.0.0",
    "@storybook/addon-links": "^4.0.0",
    "@storybook/addon-notes": "^4.0.0",
    "@storybook/addons": "^4.0.0",
    "@storybook/angular": "^4.0.0",
    "@types/jasmine": "~2.8.8",
    "@types/jasminewd2": "~2.0.3",
    "@types/jquery": "^3.3.9",
    "@types/node": "^10.12.1",
    "@types/react": "^16.4.14",
    "@types/toastr": "^2.1.35",
    "babel-loader": "^8.0.4",
    "codelyzer": "^4.5.0",
    "jasmine": "3.2.0",
    "jasmine-core": "3.2.0",
    "jasmine-reporters": "^2.3.2",
    "jasmine-spec-reporter": "~4.2.1",
    "karma": "~2.0.4",
    "karma-chrome-launcher": "~2.2.0",
    "karma-cli": "~1.0.1",
    "karma-coverage-istanbul-reporter": "^2.0.1",
    "karma-jasmine": "^1.1.2",
    "karma-jasmine-html-reporter": "1.3.1",
    "karma-junit-reporter": "^1.2.0",
    "ngx-perfect-scrollbar": "^7.0.0",
    "prettier": "^1.14.3",
    "protractor": "^5.4.1",
    "react": "^16.5.2",
    "react-dom": "^16.5.2",
    "ts-node": "~7.0.1",
    "tslint": "~5.11.0",
    "tslint-config-prettier": "^1.15.0",
    "tslint-plugin-prettier": "^2.0.0",
    "typescript": "^3.1.3",
    "webdriver-manager": "^12.1.0",
    "webpack-bundle-analyzer": "^3.0.3"
}

Any idea what exactly causes this and how it can be fixed?

like image 284
skolldev Avatar asked Dec 12 '18 13:12

skolldev


2 Answers

In fact, as mentioned in one of the comments, updating to the newest Angular CLI version did the job. Patch was released, so there is no necessity to downgrade the nodejs as suggested in the link above.

like image 57
mpro Avatar answered Nov 11 '22 23:11

mpro


EPIPE errors were appearing, because tests (in TypeScript) were incorrectly using awaits. And therefore unhandled Promise rejections were happening randomly and leading to these errors. Once I've fixed incorrect usages we don't have these errors anymore on Node 10.

Try to check your tests carefully for incorrect usages of await (either missing or redundant) or just incorrect Promise chaining (for example when you forgot to return Promise from helper methods). In our case typical error was using:

browser.wait(await EC.invisibilityOf(fade)); // incorrect

instead of:

await browser.wait(EC.invisibilityOf(fade)); // correct

Update my answer the alternative solution

The following code can be called in Protractor's onPrepare() hook, for example

let currentCommand = Promise.resolve();
// Serialise all webdriver commands to prevent EPIPE errors
const webdriverSchedule = browser.driver.schedule;
browser.driver.schedule = (command: Command, description: string) => {
  currentCommand = currentCommand.then(() =>
    webdriverSchedule.call(browser.driver, command, description)
  );
  return currentCommand as any;
}

or with some additional logging:

let currentCommand = Promise.resolve();
let concurrencyCounter = 0;
// Serialise all webdriver commands to prevent EPIPE errors
const webdriverSchedule = browser.driver.schedule;
browser.driver.schedule = (command: Command, description: string) => {
  console.log(`${++concurrencyCounter} concurrent webdriver command(s). Latest command: ${description}`);
  currentCommand = currentCommand.then(() =>
    webdriverSchedule.call(browser.driver, command, description)
      .then(result => {
        concurrencyCounter--;
        return result;
      })
      .catch(error => {
        concurrencyCounter--;
        //console.lgErrLabel('Webdriver error')(command, description, error);
        console.error('Webdriver error:', command, description, error);
        throw error;
      })
  );
  return currentCommand as any;
}

Maybe it will help somebody, who also has this issue.

like image 1
Ismoil Shifoev Avatar answered Nov 12 '22 01:11

Ismoil Shifoev