Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Failed: EPIPE write EPIPE frequently seen when SELENIUM_PROMISE_MANAGER: false #4294

Open
wcainboundary opened this issue May 17, 2017 · 47 comments

Comments

@wcainboundary
Copy link

wcainboundary commented May 17, 2017

Bug report

  • Node Version: 6.9.1
  • Protractor Version: 5.1.2
  • Angular Version: 4.0.0
  • Browser(s): Chrome Version 57.0.2987.133 (64-bit)
  • Operating System and Version OS X Version 10.10.5 (14F2315)
  • Your protractor configuration file
// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/docs/referenceConf.js

/* Third-party */
let HtmlScreenshotReporter = require('protractor-jasmine2-screenshot-reporter');
let JUnitXmlReporter = require('jasmine-reporters').JUnitXmlReporter;
let SpecReporter = require('jasmine-spec-reporter').SpecReporter;

/* Custom */
let setup = require('./e2e/setup/setup');

exports.config = {
  allScriptsTimeout: 11000,
  specs: [
    './e2e/**/*.e2e-spec.ts'
  ],
  capabilities: {
    'browserName': 'chrome'
  },
  directConnect: true,
  baseUrl: 'http://localhost:4200/',
  SELENIUM_PROMISE_MANAGER: false,
  framework: 'jasmine',
  jasmineNodeOpts: {
    showColors: true,
    defaultTimeoutInterval: 30000,
    print: function() {}
  },
  useAllAngular2AppRoots: true,
  beforeLaunch: function() {
    require('ts-node').register({
      project: 'e2e'
    });
  },
  onPrepare: function() {
    jasmine.getEnv().addReporter(new SpecReporter());
    jasmine.getEnv().addReporter(new JUnitXmlReporter({
      consolidateAll: true,
      savePath: browser.params.output || 'protractor/log',
      filePrefix: 'protractor_output'
    }));
    jasmine.getEnv().addReporter(new HtmlScreenshotReporter({
      cleanDestination: true,
      dest: 'protractor/log',
      filename: 'index.html'
    }));
    setup();
  }
};
  • A relevant example test
import { browser } from 'protractor';

import { A2Page } from './app.po';
import { NavPartial } from './nav/nav.po';
import { SettingsPage } from './settings/settings.po';
import { Utils } from './utils';

let utils = new Utils();

describe('a2 root', function() {
  let page: A2Page = new A2Page();
  let navPartial: NavPartial = new NavPartial();
  let settingsPage: SettingsPage = new SettingsPage();

  it('should be able to navigate to', () => {
    return page.navigateTo();
  });

  it('should take user to Settings', () => {
    return settingsPage.getTitle().then(title => {
      return expect(title).toEqual('Title');
    }).then(() => {
      return settingsPage.getSubtitle();
    }).then(subtitle => {
      return expect(subtitle).toEqual('Subtitle');
    });
  });

  it('should have a Home menu', () => {
    return page.navigateTo().then(() => {
      return navPartial.isHomePresent();
    }).then(present => {
      return expect(present).toBeTruthy();
    });
  });

  it('should have an Info menu', () => {
    return page.navigateTo().then(() => {
      return navPartial.isInfoPresent();
    }).then(present => {
      return expect(present).toBeTruthy();
    });
  });
});
  • Output from running the test
$ npm run e2e -- --params.baseUrl 'https://myurl'

> a2@0.0.0 pree2e /Users/me/a2
> webdriver-manager update

[13:56:14] I/update - chromedriver: file exists /Users/me/a2/node_modules/protractor/node_modules/webdriver-manager/selenium/chromedriver_2.29.zip
[13:56:14] I/update - chromedriver: unzipping chromedriver_2.29.zip
[13:56:14] I/update - chromedriver: setting permissions to 0755 for /Users/me/a2/node_modules/protractor/node_modules/webdriver-manager/selenium/chromedriver_2.29
[13:56:14] I/update - chromedriver: chromedriver_2.29 up to date
[13:56:14] I/update - selenium standalone: file exists /Users/me/a2/node_modules/protractor/node_modules/webdriver-manager/selenium/selenium-server-standalone-3.4.0.jar
[13:56:14] I/update - selenium standalone: selenium-server-standalone-3.4.0.jar up to date
[13:56:14] I/update - geckodriver: file exists /Users/me/a2/node_modules/protractor/node_modules/webdriver-manager/selenium/geckodriver-v0.16.1.tar.gz
[13:56:14] I/update - geckodriver: unzipping geckodriver-v0.16.1.tar.gz
[13:56:14] I/update - geckodriver: setting permissions to 0755 for /Users/me/a2/node_modules/protractor/node_modules/webdriver-manager/selenium/geckodriver-v0.16.1
[13:56:14] I/update - geckodriver: geckodriver-v0.16.1 up to date

> a2@0.0.0 e2e /Users/me/a2
> $(npm bin)/protractor "--params.baseUrl" "https://myurl"

[13:56:16] I/launcher - Running 1 instances of WebDriver
[13:56:16] I/direct - Using ChromeDriver directly...
Spec started

  a2 root
    ✓ should be able to navigate to
    ✓ should take user to Settings
    ✓ should have a Home menu
    ✗ should have an Info menu
      - Failed: EPIPE write EPIPE

**************************************************
*                    Failures                    *
**************************************************

1) a2 root should have an Info menu
  - Failed: EPIPE write EPIPE

Executed 4 of 4 specs (1 FAILED) in 22 secs.
[13:56:41] I/launcher - 0 instance(s) of WebDriver still running
[13:56:41] I/launcher - chrome #01 failed 1 test(s)
[13:56:41] I/launcher - overall: 1 failed spec(s)
[13:56:41] E/launcher - Process exited with error code 1

npm ERR! Darwin 14.5.0
npm ERR! argv "/Users/me/.nvm/versions/node/v6.9.1/bin/node" "/Users/me/.nvm/versions/node/v6.9.1/bin/npm" "run" "e2e" "--" "--params.baseUrl" "https://myurl"
npm ERR! node v6.9.1
npm ERR! npm  v3.10.8
npm ERR! code ELIFECYCLE
npm ERR! a2@0.0.0 e2e: `$(npm bin)/protractor "--params.baseUrl" "https://myurl"`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the a2@0.0.0 e2e script '$(npm bin)/protractor "--params.baseUrl" "https://myurl"'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the a2 package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     $(npm bin)/protractor "--params.baseUrl" "https://myurl"
npm ERR! You can get information on how to open an issue for this project with:
npm ERR!     npm bugs a2
npm ERR! Or if that isn't available, you can get their info via:
npm ERR!     npm owner ls a2
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR!     /Users/me/a2/npm-debug.log

Also excerpt from npm-debug.log:

18 verbose stack Exit status 1
18 verbose stack     at EventEmitter.<anonymous> (/Users/me/.nvm/versions/node/v6.9.1/lib/node_modules/npm/lib/utils/lifecycle.js:255:16)
18 verbose stack     at emitTwo (events.js:106:13)
18 verbose stack     at EventEmitter.emit (events.js:191:7)
18 verbose stack     at ChildProcess.<anonymous> (/Users/me/.nvm/versions/node/v6.9.1/lib/node_modules/npm/lib/utils/spawn.js:40:14)
18 verbose stack     at emitTwo (events.js:106:13)
18 verbose stack     at ChildProcess.emit (events.js:191:7)
18 verbose stack     at maybeClose (internal/child_process.js:877:16)
18 verbose stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:226:5)
  • Steps to reproduce the bug
  1. Use approximately the Node and Angular versions mentioned, Chrome browser, possibly Mac OS X. (Not yet certain how specific issue is to that combination.)
  2. Set SELENIUM_PROMISE_MANAGER: false in config (disable control flow).
  3. Due to (2) above, use promises everywhere in your test suite.
  4. Have a suite that for each of several tests, gets a URL and clicks or checks element presence.
  5. Very quickly you will start hitting Failed: EPIPE write EPIPE errors unpredictably.

I'm not using await. I cannot identify any unhandled promises in the test code either (and I'm experienced with promises), although that has been suggested in some of the comments, so I have to allow for that possibility. Still, it's surprising that node would crash on an unhandled promise, if that's the case. So it seems there's a node bug in here somewhere, in addition to whatever problem there may be in my test or protractor or webdriver, etc.

  • The URL you are running your tests against (if relevant)

Sorry, it's not public.

@evankleist
Copy link

evankleist commented May 26, 2017

I've been bumping into this quite often as well. It seems like it happens more often, maybe exclusively, when Chrome is in the background. Might just be a coincidence

@marcincharezinski
Copy link

Yes I got this ugly error too!

@NickTomlin
Copy link
Contributor

Apologies for the late response here; I haven't gotten around to reproducing this. Could one of you provide a small example repo (you could use https://github.com/NickTomlin/protractor-mcve as a starter) of an angular 2 app that reproduces this?

Removing the control flow is a step in the right direction but it may be revealing some issues (like this one) that we will need to account for. Thanks!

@marcincharezinski
Copy link

@NickTomlin @wcainboundary I just upgraded my nodejs to the latest stable version and it works fine now.

Didn't work:

$node -v
v6.10.1

Works fine:

$node -v
v7.10.0

@evankleist
Copy link

I am seeing the error in node v8.0.0

@jdmarshall
Copy link

jdmarshall commented Jun 1, 2017

I'm also seeing this error without protractor (straight webdriver.js@3.4 and I believe 3.3 before it). Never happens on OS X, but quite frequently on our build agents (Linux).

I haven't seen this issue filed against Selenium, but it probably should be.

@jessehonest
Copy link

I have seen this error in OSX.

For me the issue was timing related. My test was trying to interact with an element that was not available. Although the angular tasks were complete some rendering on the page was not complete which led to this issue. It was easier to reproduce on our hosted grid since the connections were slower.

I did see this with waitForAngularEnabled set to true and false.

@jdmarshall
Copy link

Prior to upgrading, we used to get timeout errors on some of the same tests. I wonder if Webdriver 3.x is just saying the same thing a different way...

@burkel24
Copy link

burkel24 commented Jul 6, 2017

+1 on this, running into the same issue when running my specs locally on OS X 10.12.5

@wluu
Copy link

wluu commented Jul 20, 2017

For what it's worth, I was less likely to see the EPIPE error on:

  • Node 7.10.1
  • OSX 10.12.5
  • Protactor 5.1.2
  • Chrome 59.0.3071.115

And, when I say less likely, I mean that when I ran my suite 7 times with my above configuration, 4 of the runs were successful if I immediately focused my Chrome browser and didn't move my mouse from the Chrome dock icon (probably not related).

@devoto13
Copy link
Contributor

In our project 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 8.

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

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

@SrivaniA
Copy link

Is this issue fixed ? I still see it with node version 7.7.3 and protractor version 5.1.1

@devoto13
Copy link
Contributor

devoto13 commented Sep 11, 2017

@sri1987 see my comment above. It's most likely issue in your code, not in Protractor.

@devoto13
Copy link
Contributor

@sri1987 If it's not reproducible consistently it's definitely related to missing/extra await somewhere.

@Juansasa
Copy link

Juansasa commented Oct 9, 2017

Got these error very often lately with SELENIUM_PROMISE_MANAGER:false
When running multiple tests

@renehamburger
Copy link

The issue here and in #4507 seems to be concurrent webdriver commands. @wvanderdeijl suggested a solution for the particular case of ElementArrayFinder::map() in #4508. Until this is resolved properly, the following wrapper for browser.driver.schedule(), which creates a queue to prevent any concurrent webdriver commands being executed, might be a workaround.

Can someone who's experiencing EPIPE-errors regularly test this? It may slow down the test execution to some degree.

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;
}

@Juansasa
Copy link

@renehamburger
I think you are spot on there. I narrowed down most of my errors were coming from functions which returns a Promise.all call so i'm quite sure it must have something to do with concurrency

@Xaz16
Copy link

Xaz16 commented Jan 16, 2018

@renehamburger thank you. After add this one to onPrepare section of my protractor.conf.js:

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

Error 'Failed: EPIPE write EPIPE' is gone.

@Mokkapps
Copy link

@Xaz16: Worked for us as workaround, thanks!

But the "EPIPE write EPIPE" erroms seems to be a bug in Selenium: SeleniumHQ/selenium#5345 which will be solved in 4.0.0.

So we have to wait until Protractor uses 4.0.0 version and the we can remove this workaround.

@CrispusDH
Copy link
Contributor

Do we have some link to Protractor roadmap? Or it doesn't exist at all

@CrispusDH
Copy link
Contributor

@renehamburger , could you help? I try to re-write your workaround in case when SELENIUM_PROMISE_MANAGER: false. Currently, if I just copy/past your solution there are a lot of strange issues that I feel could be resolved using async/await.

@Mokkapps
Copy link

@CrispusDH I had to change the code snippet to

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

So basically remove the .driver

@anilparkin
Copy link

Using Async/await seems to be a bigger mess than the controlFlow.

The error is still observed on Mac OS Sierra even after trying the above solution.

Is there any other solution that can try.

Thanks

@danigar
Copy link

danigar commented May 8, 2018

In our case seems to be a wrong use of async/await in some assertions.

had this:

    const modal = await page.getModalInfo()
    expect(modal.isDisplayed()).toBeTruthy()

instead of:

    const modal = page.getModalInfo()
    expect(await modal.isDisplayed()).toBeTruthy()

@marcincharezinski
Copy link

Hi @danigar Function isDisplayed() returns promise so it is essential to use await if you want to resolve it. So your second line of code in second example looks fine.
What about await in your first line, it depends on what return getModalInfo(). It is unclear at this point and I can't see connection between 1st and 2nd lines.

@CrispusDH
Copy link
Contributor

@marcincharezinski jasmine will resolve Promise in except() by yourself without await.

@danigar
Copy link

danigar commented May 24, 2018

Yep. Sorry for the delay @marcincharezinski. The getModalInfo() method of the first line returned an ElementFinder (not wrapped in a Promise), and as you see in the first example we were awaiting for it.
We had some issues like these and once we fixed them the EPIPE error went away 😊.

@hal-bot
Copy link

hal-bot commented Jun 18, 2018

@CrispusDH - I used to think the same thing until I kept getting issues around tests failing for reasons I couldn't understand. I went back and added await inside my except() statements and that cleared them up.

@kahan002
Copy link

kahan002 commented Jul 20, 2018

@Mokkapps At least in TypeScript your code gives the error:
Type '(command: Command, description: string) => Promise void' is not assignable to type ' T (command: Command, description: string) => Promise T'.
Type 'Promise void' is not assignable to type 'Promise T'.
Property 'cancel' is missing in type 'Promise void'.

@Mokkapps
Copy link

Mokkapps commented Jul 24, 2018

@kahan002

We finally solved it using this code

function patchSchedule() {
  if (os.platform() === 'darwin') {
    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) => {
      currentCommand = currentCommand.then(() =>
        webdriverSchedule
          .call(browser.driver, command, description)
          .then(result => {
            concurrencyCounter--;
            return result;
          })
          .catch(error => {
            concurrencyCounter--;
            // tslint:disable-next-line:no-console
            console.error('Webdriver error:', command, description, error);
            throw error;
          })
      );
      return currentCommand as any;
    };
  }
}

which is called in protractor.conf.ts

onPrepare: () => { patchSchedule(); },

@kahan002
Copy link

kahan002 commented Jul 24, 2018

Thanks @Mokkapps for sharing that. A couple of notes in case someone wants to adapt it for typeScript and an environment like mine. os.platform() was not known, so I used process.platform. I had to import { Command } from "selenium-webdriver"; I had to comment out the concurrencyCounter since it was never read. And since I have typeScript warning on implicit any, I needed to make them explicit in .then((result : any) => { and .catch((error: any) => {. I am not complaining about the code, and I am happy you shared it (it seems to fix the issue, though it's a bit hard to tell since it was intermittent). I hope that this comment is helpful to someone. Thanks so much for getting back to me and others.
But perhaps my changes broke your fix, because I just got UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 4): Error: EPIPE write EPIPE
(node:8514) [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.
after all. I'll go back and see where I must be misusing await.

@lukaslewandowski-pearson

Any progress for OSX users?

@kylecordes
Copy link

I think this might be triggered by the same situation as some other similar errors, the fix for which is to use HTTP keep-alive in the communication between the Selenium Node code and the browser. There is a fix for this in the Selenium mainline, last year - but it is not published in any version of that code.

Here is the workaround we use here, borrowed and edited from something another commenter wrote in another issue. Set up a NPM package.script to run it:

"scripts": {
    "install": "webdriver-manager update && node keep-alive-patch.js",

The patcher code is:

const fs = require('fs');
const chromeFile = 'node_modules/selenium-webdriver/chrome.js';
fs.readFile(chromeFile, 'utf8', function (err, data) {
  if (err)
    throw err;

  const result = data.replace(/new http.HttpClient\(url\)/g,
    "new http.HttpClient(url, new (require('http').Agent)({ keepAlive: true }))");
  console.log(`Patching ${chromeFile}`);
  fs.writeFileSync(chromeFile, result, 'utf8');
});

With this patch, Protractor is 99%+ robust for us on both Windows and OSX, using SELENIUM_PROMISE_MANAGER: false. Your mileage may vary, depending on whether your EPIPE error is caused by the same underlying situation as ours way.

@kahan002
Copy link

kahan002 commented Jul 31, 2018

I find that awaits with chains (or over arrays) seem most vulnerable. So for instance I just saw the error with let testFormatID: string =await element.all(by.className('ng-star-inserted')).all(by.tagName('td')).get(1).getText(); It is possible that the error is mine and that what I have written should not work.

@kahan002
Copy link

#4792 seems to have fixed my issues on Mac OS X. Thanks for the tip, IgorDorokhov .

@IgorDorokhov
Copy link

@kahan002 you are welcome!

@rafalf
Copy link

rafalf commented Aug 6, 2018

any ETA for 4.0.0-alpha.1 included in protractor?

@demisx
Copy link

demisx commented Sep 11, 2018

#4792 did not fix the problem for me. Still getting Failed: EPIPE write EPIPE error 1 out of 5 doing filtering on ElementArrayFinder:

$$('classified-section').filter((section) => section.isDisplayed())

Please upgrade to selenium-webdriver@4.0.0-alpha.1. It seems to be resolved there.

@rafalf
Copy link

rafalf commented Sep 13, 2018

@demisx I patched it here and it works for me

@demisx
Copy link

demisx commented Sep 13, 2018

@rafalf Thank you. If you are talking about "taking the index.js from selenium-3.7.0 and adding ECONNREFUSED" then I've tried that, but was still getting this error occasionally. Please let me know if I misunderstood your comment.

@demisx
Copy link

demisx commented Oct 30, 2018

The EPIPE error still happens quite often with latest protractor 5.4.1, chromedriver_2.43 and async/await on MacOS Mojave. We can't run E2E specs on CI anymore. Take multiple manual runs until all of them pass. Very unstable.

@rafalf
Copy link

rafalf commented Oct 30, 2018

@demisx
this is mainly happening for me for each , filter and other functions that are used iwth arrays

how I reworked it

        // EPIPE write EPIPE
        // await $$("short-list-component.ng-valid mat-label").each(async function (element) {
        //     labels.push(await element.getText())
        // });
        // this.logInfo("getMatLabels: " + labels);
        // return labels

        let l = await $$("q-short-list-component.ng-valid mat-label");
        for (let element of l){
            text = await element.getText();
            labels.push(text)
        }

@demisx
Copy link

demisx commented Oct 30, 2018

@rafalf Yeah, that was the first thing we got rid of. Though, it reduced the frequency of EPIPE errors, they did not go away completely. It's getting worse when running protractor with multiple capabilities. So, far @kylecordes patch seems to be doing the job. Thank you @kylecordes! Hopefully, this fix will make it to master soon.

Off topic, you don't need await in let l = await $$("q-short-list-component.ng-valid mat-label"). The $$ returns ElementArrayFinder, not a promise. 😉

@rafalf
Copy link

rafalf commented Oct 30, 2018

@demisx no you are wrong , maybe thats why you get still EPIPE errors 💃
Yes - it returns ElementArrayFinder w/o await but you wont be able to iterate over it
and this part would not work

for (let element of l){
            text = await element.getText();
            labels.push(text)
        }

if i do await, I get a list of elements ;) that I can go through

@demisx
Copy link

demisx commented Oct 30, 2018

@rafalf Sorry, my bad. I missed the iteration part below the await. You are absolutely correct.

@yyankowski
Copy link

I may be mistaken but it looks like such errors intermittently happen for me wherever there is a usage of ElementArrayFinder in the following way:
await $$('some-selector').click()

@demisx
Copy link

demisx commented Nov 28, 2018

@yyankowski Yes, it was my experience as well. I saw this error happening with $$ more than anything else. Especially, when trying to call a method on the ElementArrayFinder returned by $$.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests