How to fix StaleElementReferenceError for selenium?

Viewed 91

I have the problem, that I always get the error StaleElementReferenceError: stale element reference: element is not attached to the page document when I want to get the text of the body of a page with selenium. I already tried to use something to fix it but it didn't work.

My code:

function eduMobile(driver)
{
  driver.get(process.env.URL)
  
  // PIN login
  const pinEntry = driver.findElement(By.xpath('//*[@id="inputPin"]'))
  pinEntry.sendKeys(process.env.PIN)

  const pinOkBtn = driver.findElement(By.xpath('/html/body/div/form/input[2]'))
  pinOkBtn.click()

  // get body
  var mobile_body = driver.findElement(By.xpath("/html/body"))
  mobile_body.getText().then(function (text) {
    console.log(text);
  });

}

I tried to fix the error with the following code, but it didn't work

mobile_body.getText().then(function (text) {
    console.log(text);
  });

My driver init:

  let driver = new webdriver.Builder()
    .forBrowser(Browser.CHROME)
    .setChromeOptions(new chrome.Options().headless())
    .build()

Full error:

C:\Users\andri\node_modules\selenium-webdriver\lib\error.js:522
    let err = new ctor(data.message)
              ^

StaleElementReferenceError: stale element reference: element is not attached to the page document
  (Session info: headless chrome=102.0.5005.115)
    at Object.throwDecodedError (C:\Users\andri\node_modules\selenium-webdriver\lib\error.js:522:15)
    at parseHttpResponse (C:\Users\andri\node_modules\selenium-webdriver\lib\http.js:549:13)
    at Executor.execute (C:\Users\andri\node_modules\selenium-webdriver\lib\http.js:475:28)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async thenableWebDriverProxy.execute (C:\Users\andri\node_modules\selenium-webdriver\lib\webdriver.js:735:17) {
  remoteStacktrace: 'Backtrace:\n' +
    '\tOrdinal0 [0x0064D953+2414931]\n' +
    '\tOrdinal0 [0x005DF5E1+1963489]\n' +
    '\tOrdinal0 [0x004CC6B8+837304]\n' +
    '\tOrdinal0 [0x004CF0B4+848052]\n' +
    '\tOrdinal0 [0x004CEF72+847730]\n' +
    '\tOrdinal0 [0x004CF200+848384]\n' +
    '\tOrdinal0 [0x004F4FDF+1003487]\n' +
    '\tOrdinal0 [0x0051449C+1131676]\n' +
    '\tOrdinal0 [0x004EFC74+982132]\n' +
    '\tOrdinal0 [0x005146B4+1132212]\n' +
    '\tOrdinal0 [0x00524812+1198098]\n' +
    '\tOrdinal0 [0x005142B6+1131190]\n' +
    '\tOrdinal0 [0x004EE860+976992]\n' +
    '\tOrdinal0 [0x004EF756+980822]\n' +
    '\tGetHandleVerifier [0x008BCC62+2510274]\n' +
    '\tGetHandleVerifier [0x008AF760+2455744]\n' +
    '\tGetHandleVerifier [0x006DEABA+551962]\n' +
    '\tGetHandleVerifier [0x006DD916+547446]\n' +
    '\tOrdinal0 [0x005E5F3B+1990459]\n' +
    '\tOrdinal0 [0x005EA898+2009240]\n' +
    '\tOrdinal0 [0x005EA985+2009477]\n' +
    '\tOrdinal0 [0x005F3AD1+2046673]\n' +
    '\tBaseThreadInitThunk [0x767B6739+25]\n' +
    '\tRtlGetFullPathName_UEx [0x777E8FEF+1215]\n' +
    '\tRtlGetFullPathName_UEx [0x777E8FBD+1165]\n'
}

Thanks for helping in advance!

1 Answers

I assume the following code triggers a redirect/page re-render?

const pinOkBtn = driver.findElement(By.xpath('/html/body/div/form/input[2]'))
pinOkBtn.click()

StaleElementReferenceError are caused when you've a WebElement assigned to a variable, then cause that WebElement (or the entire page) to be rerendered, so the driver is no longer able to pinpoint that exact DOM element any more.

I guess this is what's happening in your situation - the button is clicked and immediately you're querying the DOM and assigning the body to a variable and then working with that - in the meantime the page has been rerendered.

Just as a sanity check try setting a breakpoint at

var mobile_body = driver.findElement(By.xpath("/html/body"))

And waiting until the page is completely loaded before resuming the debugging. If this works then you just need to wait until the page is completely loaded, e.g. using a Wait. In Java it'd look something like this:

    final String mySelector = "Some css selector (or xpath, or id) of an element on the page which would indicate that the page has been fully loaded";
    FluentWait<WebDriver> wait = new FluentWait<>(getDriver())
            .withTimeout(Duration.ofSeconds(10))
            .pollingEvery(Duration.ofSeconds(1))
            .ignoring(NullPointerException.class)
            .ignoring(StaleElementReferenceException.class);
    wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector(mySelector)));
Related