StaleElementReferenceException with UIautomator2

Hi Guys,

Since we’ve moved to UIautomator2 framework , “StaleElementReferenceException” makes our execution very sad :slight_smile:

I was wondering how do you workaround this ?

The obvious solution “not to cache” the element and each time execute driver.findElementBy… is standing against the PO concept …

All our elements are Page’s properties annotated with @FindBy , if we will look for them manually each time they are needed , we are missing the entire concept…

I was wonder if there a way to make a refresh for the PageObject and by that to refresh all the cached elements ?

Thanks

1 Like

can you put a sample code here, to reproduce the issue.

 @AndroidFindBy(id = UIStrings.POSITION_FIXED_INCOME_TOTAL)
    private AndroidElement totalMoneyInTitle;


   public void validateTitleIsEqualSubAssets()
    {
        AbstractAppiumConnection.webDriverWait.until(new ExpectedCondition<Boolean>() {
            @Nullable
            @Override
            public Boolean apply(@Nullable WebDriver webDriver) {
                **return totalMoneyInTitle.isDisplayed();//cause to StaleException --> appium server hangs**
            }
        });
        BigDecimal title = getTotalMoneyInTheTitle();
        BigDecimal totalSubAssets = calculateTotalSumOfSubAssetsInTab();
        Assert.assertEquals("Total cash holdings is not equals total tabs",title,totalSubAssets);
    }

I do something like below, and i don’t notice stale element exception. I would suggest make sure you are on the right page and then make a call to isDisplayed().

public void waitForWebElement(WebElement weblement){
try {
new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOf(weblement));
}
catch(Exception ex){

        System.out.println("WebElement "+weblement.toString() +" not found");
    }

}

@igal_epshtein i used similar to @Venkatesh without issues. BUT this is for WEB!

    public Boolean waitElementForVisibility(List<WebElement> el) {
        return waitElementForVisibility(el, 0, 10);
    }

    public Boolean waitElementForVisibility(List<WebElement> el, int num) {
        return waitElementForVisibility(el, num, 10);
    }

    public Boolean waitElementForVisibility(List<WebElement> el, int num, int seconds) {
        WebDriverWait wait = new WebDriverWait(driver, seconds);
        try {
            WebElement element = wait.until(
                    ExpectedConditions.visibilityOf(el.get(num)));
            if (element.isDisplayed())
                return true;
            else
                return false;
        } catch (Exception e) {
            return false;
        }
    }

for Android NATIVE you should use directly:

    @AndroidFindBy(id = "title")
    private List<AndroidElement> dialogTitle;

    public String getDialogTitle() {
        if (dialogTitle.isEmpty())
            return null;
        else
            return dialogTitle.get(0).getText();
    }

where timeout for dialogTitle is set in page init:

PageFactory.initElements(new AppiumFieldDecorator(driver, DEFAULT_WAIT_TIME, SECONDS), this);

but this one doesn’t answer the stalerefernce issue …

The stalereference occurs once the application view is being destroyed and created once again , then the page’s object is pointing to “old” view element which actually doesn’t exist anymore …

I was wonder if there is a way to “refresh” the page object , and to initialise it with new view elements

@igal_epshtein page object does not point to anywhere. element starts finding whenever you call it find not at the moment of page object init.

once you’ve used the page object , it has a reference to view’s object , in case and the last one was recreated you get Stale exception…

@igal_epshtein you are wrong :grinning: . it has reference to object but not elements mentioned in object. Thus whenever e.g. you try to click in page object by element each time it will start looking for element from zero. There is strategy to override this. But you need enable cache strategy which is other story.

@Aleksei not sure you are right :slight_smile:

I’m getting the stale exception on the same line of code always after the view was recreated (some application’s flow)

@igal_epshtein try to see appium logs with following test:

  1. do click to simple text file several times

Result: with every click first command search for element -> then click to element by found element ID.

anyway suggestion: do clicker function and point to it EVERY click in page objects. in clicker when you see stale error do e.g. pause for 100ms and retry click. Limit this e.g. to 5 tries to avoid loop. good luck :slight_smile:

@Aleksei - this is not happens with click only , but every operation on the page (isDisplayed , setText…)

Apium guys should fix this issue for UIAutomator2 package :wink:

2 Likes

@igal_epshtein wow something new for me :slight_smile:

Hi ,
Am also facing the same issue for UIAutomator2

I too am facing this issue. If I put the thread to sleep for a second before accessing someElement.isDisplayed(), then I do not get the StaleElementReferenceException, but this dramatically increases test execution time for large tests (it’s also very ugly, I was told not to use sleeps).

There must be another way… :thinking:

Hello guys, I am still facing this issue, any updates?

I think i have solved it.
My problem was that the element was showing on screen but appium couldn’t find it.
As funny as it may seem, resetting my TouchAction object did the work.
I just added at the start of the function:
touchAction = new TouchAction(driver);
so if you are using a TouchAction object, try resetting it.
I am using 2 Android drivers simultaneously so appium was recognising the other device’s page.

1 Like

Hi guys,

I’m using Java Appium 7.2.0, Appium 1.17.0 and PageFactory approach and get StaleElementReferenceException after element is found.
After reviewing video of the automation session it does seem like Android view is being recreated in an instant. Is there any possible solution how to handle such issue?

Here are some Appium logs:

2020-10-21 21:43:41:720 - [debug] [MJSONWP (7130dace)] Calling AppiumDriver.findElement() with args: ["accessibility id","phoneNumberField","7130dace-87d0-4e24-be9e-46cbb5c97af6"]
2020-10-21 21:43:41:721 - [debug] [BaseDriver] Valid locator strategies for this request: xpath, id, class name, accessibility id, -android uiautomator
2020-10-21 21:43:41:721 - [debug] [BaseDriver] Waiting up to 0 ms for condition
2020-10-21 21:43:41:722 - [debug] [WD Proxy] Matched '/element' to command name 'findElement'
2020-10-21 21:43:41:722 - [debug] [WD Proxy] Proxying [POST /element] to [POST http://127.0.0.1:8202/wd/hub/session/828dacc9-510e-4030-af54-1d10f296ea6c/element] with body: {"strategy":"accessibility id","selector":"phoneNumberField","context":"","multiple":false}
2020-10-21 21:43:42:172 - [debug] [WD Proxy] Got response with status 200: {"sessionId":"828dacc9-510e-4030-af54-1d10f296ea6c","value":{"ELEMENT":"b86f31c5-e703-4d1c-a984-89256ea60666","element-6066-11e4-a52e-4f735466cecf":"b86f31c5-e703-4d1c-a984-89256ea60666"}}
2020-10-21 21:43:42:173 - [debug] [MJSONWP (7130dace)] Responding to client with driver.findElement() result: {"element-6066-11e4-a52e-4f735466cecf":"b86f31c5-e703-4d1c-a984-89256ea60666","ELEMENT":"b86f31c5-e703-4d1c-a984-89256ea60666"}
2020-10-21 21:43:42:174 - [HTTP] <-- POST /wd/hub/session/7130dace-87d0-4e24-be9e-46cbb5c97af6/element 200 454 ms - 199
2020-10-21 21:43:42:174 - [HTTP] 
2020-10-21 21:43:42:448 - [HTTP] --> GET /wd/hub/session/7130dace-87d0-4e24-be9e-46cbb5c97af6/element/b86f31c5-e703-4d1c-a984-89256ea60666/displayed
2020-10-21 21:43:42:448 - [HTTP] {}
2020-10-21 21:43:42:449 - [debug] [MJSONWP (7130dace)] Calling AppiumDriver.elementDisplayed() with args: ["b86f31c5-e703-4d1c-a984-89256ea60666","7130dace-87d0-4e24-be9e-46cbb5c97af6"]
2020-10-21 21:43:42:452 - [debug] [WD Proxy] Matched '/element/b86f31c5-e703-4d1c-a984-89256ea60666/attribute/displayed' to command name 'getAttribute'
2020-10-21 21:43:42:452 - [debug] [WD Proxy] Proxying [GET /element/b86f31c5-e703-4d1c-a984-89256ea60666/attribute/displayed] to [GET http://127.0.0.1:8202/wd/hub/session/828dacc9-510e-4030-af54-1d10f296ea6c/element/b86f31c5-e703-4d1c-a984-89256ea60666/attribute/displayed] with body: {}
2020-10-21 21:43:42:747 - [WD Proxy] Got response with status 404: {"sessionId":"828dacc9-510e-4030-af54-1d10f296ea6c","value":{"error":"stale element reference","message":"The element 'By.accessibilityId: phoneNumberField' does not exist in DOM anymore","stacktrace":"
io.appium.uiautomator2.common.exceptions.StaleElementReferenceException: The element 'By.accessibilityId: phoneNumberField' does not exist in DOM anymore
io.appium.uiautomator2.model.KnownElements.restoreCachedElement(KnownElements.java:103)
io.appium.uiautomator2.model.KnownElements.getElementFromCache(KnownElements.java:122)
io.appium.uiautomator2.handler.GetElementAttribute.safeHandle(GetElementAttribute.java:26)
io.appium.uiautomator2.handler.request.SafeRequestHandler.handle(SafeRequestHandler.java:38)
io.appium.uiautomator2.server.AppiumServlet.handleRequest(AppiumServlet.java:252)
io.appium.uiautomator2.server.AppiumServlet.handleHttpRequest(AppiumServlet.java:242)
io.appium.uiautomator2.http.ServerHandler.channelRead(ServerHandler.java:51)\n\tat io.netty.chan...
2020-10-21 21:43:42:748 - [debug] [W3C] Matched W3C error code 'stale element reference' to StaleElementReferenceError

wait is good solution but unfortunately doesn’t work always

1 Like