1

I use edge webdriver to find element on page (SPA), and immediately simulate click.

However, I'm getting OpenQA.Selenium.StaleElementReferenceException: stale element reference: element is not attached to the page document.

In case the element was rerendered by the SPA framework between finding element and clicking, I've added some retry logic, but I'm still getting the error.

IWebElement FirstCell => Driver.FindElementsByCssSelector(".simple-grid .sg-row>.sg-cell").FirstOrDefault();


void Test()
{
  try 
  {
    FirstCell.Click();
  }
  catch (StaleElementReferenceException)
  {
    FirstCell.Click(); //retry - this should find element againand return new instance
  }
}

Notice, that in the retry block I get fresh element reference

Liero
  • 25,216
  • 29
  • 151
  • 297
  • Does this answer your question? [Selenium WebDriver How to Resolve Stale Element Reference Exception?](https://stackoverflow.com/questions/16166261/selenium-webdriver-how-to-resolve-stale-element-reference-exception) – Prophet Jul 27 '21 at 17:36
  • Not really. I'm not caching or storing the element reference anywhere, that's what confuses me – Liero Jul 27 '21 at 17:42

1 Answers1

0

As described here and in many other tutorials and questions describing the StaleElementReferenceException by Driver.FindElementsByCssSelector(".simple-grid .sg-row>.sg-cell") command you actually catching the web element matching the passed locator and storing a reference to it in IWebElement FirstCell.
But since the web page is still dynamically changing, not yet finally built, a moment after that the reference you stored becomes stale, old, invalid since the web element was changed.
This is why by involving the FirstCell.Click() inside the try block you are getting the StaleElementReferenceException.
Trying to involve the absolutely same action inside the catch block will throw StaleElementReferenceException again since you still using the already known as invalid (stale) FirstCell reference.
What you can do to make your code work is to get that element reference Again inside the catch block and try click it.
Like this:

IWebElement FirstCell => Driver.FindElementsByCssSelector(".simple-grid .sg-row>.sg-cell").FirstOrDefault();


void Test()
{
  try 
  {
    FirstCell.Click();
  }
  catch (StaleElementReferenceException)
  {
    FirstCell = Driver.FindElementsByCssSelector(".simple-grid .sg-row>.sg-cell").FirstOrDefault();
    FirstCell.Click(); //retry - Now this indeed should find element again and return new instance
  }
}

However this will also not surely work since possibly the page is still not fully, finally stable.
To make this work you can do this in a loop, something like this:

void Test()
{
  IWebElement FirstCell;
  for(int i=0;i<10;i++){
    try 
    {
      FirstCell = Driver.FindElementsByCssSelector(".simple-grid .sg-row>.sg-cell").FirstOrDefault();
      FirstCell.Click();
    }
    catch (StaleElementReferenceException)
    {
      System.Threading.Thread.Sleep(200);
    }
  }
}
Prophet
  • 32,350
  • 22
  • 54
  • 79
  • But I'm not storing the reference in FirstCell property. Each time the `FirstCell` property is accessed, getter in invoked which calls to `Driver.FindElementsByCssSelector`. Notice it is a property, not a field or a variable – Liero Jul 28 '21 at 06:40
  • I can't see that from your code, but if you are sure your code actually invokes `Driver.FindElementsByCssSelector` each time `FirstCell` is referenced - calling that from loop as I shown can resolve the problem while giving only one more chance immediately, without delay may not work in case the element is being changed several times during the page loading process. So please try using the loop approach as I wrote and please let me know if that helped. – Prophet Jul 28 '21 at 12:12