SeleniumLibrary: StaleElementReferenceException with Wait* keywords
With Chrome 44.0.2403, Chrome driver 2.16 Selenium2Library 1.7.2 and selenium 2.46.1 when I use Wait* keywords, the StaleElementReferenceException might occur. Documentation says that keyword should only fail if condition is not met before the timeout, example for Wait Until Page Contains Element keyword, documentation says: Fails if timeout expires before the element appears.
But if StaleElementReferenceException happens, then I see this:
Selenium2Library.Wait Until Element Is Visible xpath=//span/span[text()="${menu_item}"], timeout=5s, error=Menu item ${menu_item} not found on page!
Documentation:
Waits until element specified with `locator` is visible.
Start / End / Elapsed: 20150730 14:24:49.623 / 20150730 14:24:50.240 / 00:00:00.617
00:00:00.376KEYWORD: common_library_imports.Selenium2library Common Failure
14:24:49.624 TRACE Arguments: [ u'xpath=//span/span[text()="XXXXXX"]' | timeout=u'5s' | error=u'Menu item XXXXXX not found on page!' ]
14:24:49.624 DEBUG POST http://127.0.0.1:55614/session/7f76eac90d05725647286d5bdf089b4a/elements {"using": "xpath", "sessionId": "7f76eac90d05725647286d5bdf089b4a", "value": "//span/span[text()=\"XXXXXX\"]"}
14:24:49.829 DEBUG Finished Request
14:24:49.831 DEBUG GET http://127.0.0.1:55614/session/7f76eac90d05725647286d5bdf089b4a/element/0.4323001531884074-3/displayed {"sessionId": "7f76eac90d05725647286d5bdf089b4a", "id": "0.4323001531884074-3"}
14:24:49.855 DEBUG Finished Request
14:24:50.239 FAIL StaleElementReferenceException: Message: stale element reference: element is not attached to the page document
(Session info: chrome=44.0.2403.125)
(Driver info: chromedriver=2.14.313457 (3d645c400edf2e2c500566c9aa096063e707c9cf),platform=Windows NT 6.1 SP1 x86_64)
14:24:50.239 DEBUG Traceback (most recent call last):
File "<string>", line 2, in wait_until_element_is_visible
File "C:\Python27\lib\site-packages\Selenium2Library\keywords\keywordgroup.py", line 15, in _run_on_failure_decorator
return method(*args, **kwargs)
File "C:\Python27\lib\site-packages\Selenium2Library\keywords\_waiting.py", line 128, in wait_until_element_is_visible
self._wait_until_no_error(timeout, check_visibility)
File "C:\Python27\lib\site-packages\Selenium2Library\keywords\_waiting.py", line 237, in _wait_until_no_error
timeout_error = wait_func(*args)
File "C:\Python27\lib\site-packages\Selenium2Library\keywords\_waiting.py", line 121, in check_visibility
visible = self._is_visible(locator)
File "C:\Python27\lib\site-packages\Selenium2Library\keywords\_element.py", line 723, in _is_visible
return element.is_displayed()
File "C:\Python27\lib\site-packages\selenium\webdriver\remote\webelement.py", line 323, in is_displayed
return self._execute(Command.IS_ELEMENT_DISPLAYED)['value']
File "C:\Python27\lib\site-packages\selenium\webdriver\remote\webelement.py", line 402, in _execute
return self._parent.execute(command, params)
File "C:\Python27\lib\site-packages\Selenium2Library\webdrivermonkeypatches.py", line 11, in execute
result = self._base_execute(driver_command, params)
File "C:\Python27\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 175, in execute
self.error_handler.check_response(response)
File "C:\Python27\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 166, in check_response
raise exception_class(message, screen, stacktrace)
14:24:49.621 TRACE Arguments: [ ${menu_item}=u'XXXXXX' | ${timeout}=u'10' ]
and keyword did fail immediately. But I did expect that keyword would simply re-try search for the element if the StaleElementReferenceException or any other selenium related error happens before the timeout.
About this issue
- Original URL
- State: closed
- Created 9 years ago
- Comments: 50 (36 by maintainers)
The reason I think
Wait ...keywords could ignore the stale element errors is that they already ignore errors related to elements not existing in the first place. In practice these keywords execute conditions likeself.find_element(locator).is_visible(). At the moment it’s fine iffind_element()fails due to element not existing, but it’s a failure if element exists but is invalidated before callingis_visible().In my opinion element not existing and element being invalid are so close to each others that they should be handled the same way. They both cause a failure with normal keywords, and I see no harm in both of them being ignored with wait keywords. If I’ve understood it correctly, now wait keyword passing or failing may depend on timing.
As I wrote above, I think these two error situations should be handled the same way. That could be easily and explicitly done like this:
PS: That
str(err)should actually beunicode(err)to avoid non-ASCII errors with Python 2.User’s perspective: I’ve just spent a year in a shop dealing with apps written using a framework which was basically a stale element exception generator (SAPUI5, may you burn in hell). We used the SL monkeypatched to do exactly what Pekka posted above, and it was totally fine for us. We somehow knew the behavior is sort-of wrong but we were not able to fix the framework that caused the problems (different team, big corp). As you say, especially with
Waitkeywords it’s really a nuisance because when you are waiting on some transition, you kinda expect funky things to happen in the meantime in the DOM.Holding my thumbs that a fix for this long-runner makes it into v3.3.0. That would be awesome. Thanks @aaltat and everybody else for your dedicated work with RF.
There is actually good reason why it happens randomly and why it happens “Wait Until Element Is Visible”. Understanding both of these, helps one to understand how to fix it and why fixing is actually so darn difficult.
In most of the selenium operations, like Clicks and "Wait Until Element Is Visible, there is actually two operations over the json wire protocol (from S2L to the browser). First one will locate the element and return reference to the element. Second operation will perform the click, based on the element reference. When the click is received, in the browser, selenium will check is the element reference still valid. If it’s not valid, error will be received.
The Webdriver wait functionality tries to remove the problem by allowing poll the element staleness. And polling will return when the element state is not anymore stale.
But thanks to modern browser technologies, element state is wery moving target. Example in a filter box, user types N number of letters and results is filtered. Now depending on the implementation of the application, element state can change from N * 2 (each key stroke causes state to change stale and back) to 0 (no filtering was required). Because it is impossible to know how many stale state change one should poll and how long one should wait, to be sure that error is not received it is hard to come up with universal solution to the problem.
But I am thinking and have prototypes for few solutions, but they all have their problems. And all of them require massive rewrite. But thanks from understanding and patience on the matter.