"Stale element reference" error behavior undestanding

13,443

I don't think we can be certainly sure why that happens, but you're definitely not alone (1) (2). This may be due to the way your page is rendered specifically (e.g. how your app/framework is handling rendering DOM elements), or just a Selenium/driver thing. If you're interested into an exact explanation, you might have better luck if using Protractor bug report system.

A good guess, however, may be that it is related to the way Selenium defines stale element:

A less common, but still common cause is where a JS library has deleted an element and replaced it with one with the same ID or attributes

Some libraries can fool Selenium into believing an element is gone from the DOM, but it has been really just replaced in an instant. Adding there a tight, frail timing between clicking and element being placed in the DOM (race condition basically) - that might be the cause. You might be interested in reading a little more about it here.

Anyway, if you're having such issues, I'd recommend you using browser.wait and Expected Conditions.

Expected conditions are basically functions that return true or false, and you can specify a timeout that will cause test to fail if true is not returned in that time - you can see how it's used in a similar question.

Basically, you might want to do it like this:

var EC = protractor.ExpectedConditions;
var summaryId = element(by.id('myValidationSummaryId'));

browser.wait(EC.presenceOf(summaryId), 5000);
//rest of your code
Share:
13,443
Morbia
Author by

Morbia

.Net Consultant

Updated on June 14, 2022

Comments

  • Morbia
    Morbia about 2 years

    Code 1:

    element(by.id('myButtonId')).click();
    return element(by.id('myValidationSummaryId')).getText().then(function (val) {
        return val;
    });
    

    Above code worked fine many times and then it started giving below error

    "Failed: stale element reference: element is not attached to the page document"

    this id 'myValidationSummaryId' is no where used before, clicking button posts form and success/failure message available from service side in 'myValidationSummaryId'.

    Code 2:

    return element(by.id('myButtonId')).click().then(function () {
        return element(by.id('myValidationSummaryId')).getText().then(function (val) {
          return val;
        });
    });
    

    Fixing code as above fixed original issue and it worked consistently fine many times but later it started failing randomly with original stale element reference error.

    Code 3:

    return element(by.id('myButtonId')).click().then(function () {
        return element(by.id('myValidationSummaryId')).waitReady().then(function (isReady) {
            if (isReady) {
                return element(by.id('myValidationSummaryId')).getText().then(function (val) {
                    return val;
                });
            } else {
                return 'Failed to check success/failure message';
            }
        });
    });
    

    Then I fixed code as above and now it works fine consistently, waitReady function actively wait for an element present and displayed up to specified time.

    Shouldn't protractor/WebdriverJS supposed to handle this issues fine natively.

    1> could you please explain why Code 1 and Code 2 sometime worked and sometime failed?

    2> do you think Code 3 is now fine and expected to work every time?

    Element 'myValidationSummaryId' used only once and after click so if pages is not loaded fully and if element is yet not available it should say No Element Found but why stale element reference? I have used pageLoadTimeout as 5 minutes and page is loaded in few second. This is non AngularJS application and browser.ignoreSynchronization = true.

    everywhere it talked about what code can fix it but not found much on why this behavior and why WebdriverJS itself not able to handle it.

  • Morbia
    Morbia almost 9 years
    Thank you for your suggestions, waitReady function uses browser.wait, and it works fine, I had gone through docs.seleniumhq.org/exceptions/stale_element_reference.jsp but in my case element is not removed, replaced or its type does not change.
  • wap300
    wap300 almost 9 years
    Then you'd probably need to share your exact code, or do some advanced debugging on your own. The cause will be probably very hard to determine, but if you find out what that is, I'd be great if you shared the cause here.
  • JWP
    JWP almost 9 years
    Agreed, I'm working on a project now whereby if I open up developer tools in Chrome F12 and watch the DOM, I can actually see Angular's Asynchronous puts and gets change certain (and unknown to the test) DOM elements. This makes testing these pages impossible because of obvious timing issues and the "Stale Element Reference".
  • FrankL
    FrankL about 4 years
    The definition of "stale element" you mentioned showed me the solution in my case: A master detail relationship where a change in the master record replaces the detail table, but with the same cell ids. Sometimes my test code got the reference to the old element, because it has not yet been removed from the DOM.