Appium Crash on StaleElement

Hello Guys. Need your help.

Is there any settings in appium that catch this error when this happens? I am currently trying to create a script that will answer the different element types like radio box, checkbox, carousel, etc.

All of them are named answerItem and then store in pageFactorty and then my script will either tap or swipe the carousel depending on the element type.

To check if elements are displayed, I have a self-call function with retry and try-catch all exceptions until either the element is visible or the retry counter is 0.

The script is able to select an answer from the list and taps continue button just fine. The problem is when the answerItem changes from radiobutton to carousel or v.v, the application in the android emulator will close. It’s not an app crash because the script is still running since I can see the retry counting. The appium desktop logs this error. I saw some guides using the By locator to refresh the element but I don’t know how to do that with pagefactory.

[W3C (dd989c97)] Calling AppiumDriver.elementDisplayed() with args: [“b399e514-7b8c-4d14-a54e-2ce7b149a894”,“dd989c97-1fe6-4a96-b034-aed6fe87270b”]

[WD Proxy] Matched ‘/element/b399e514-7b8c-4d14-a54e-2ce7b149a894/attribute/displayed’ to command name ‘getAttribute’

[WD Proxy] Proxying [GET /element/b399e514-7b8c-4d14-a54e-2ce7b149a894/attribute/displayed] to [GET http://127.0.0.1:8205/wd/hub/session/12ca2aa2-9eac-4efd-a766-8a8c013bc190/element/b399e514-7b8c-4d14-a54e-2ce7b149a894/attribute/displayed] with no body

[WD Proxy] Got response with status 404: {“sessionId”:“12ca2aa2-9eac-4efd-a766-8a8c013bc190”,“value”:{“error”:“stale element reference”,“message”:"Cached elements ‘By.xpath: //[contains(@content-desc, ‘answerItem’)]’ do not exist in DOM anymore",“stacktrace”:"io.appium.uiautomator2.common.exceptions.StaleElementReferenceException: Cached elements 'By.xpath: //[contains(@content-desc, ‘answerItem’)]’ do not exist in DOM anymore\n\tat io.appium.uiautomator2.model.ElementsCache.restore(ElementsCache.java:74)\n\tat io.appium.uiautomator2.model.ElementsCache.get(ElementsCache.java:146)\n\tat io.appium.uiautomator2.handler.GetElementAttribute.safeHandle(GetElementAttribute.java:23)\n\tat io.appium.uiautomator2.handler.request.SafeRequestHandler.handle(SafeRequestHandler.java:41)\n\tat io.appium.uiautomator2.server.AppiumServlet.handleRequest(AppiumServlet.java:261)\n\tat io.appium.uiautomator2.server.AppiumServlet.handleHttpRequest(AppiumServlet.java:255)\n\tat io.appium.uiautomator2.http.ServerHandler.channelRead(ServerHandler.java:68)\n\tat io.nett…

[W3C] Matched W3C error code ‘stale element reference’ to StaleElementReferenceError

[W3C (dd989c97)] Encountered internal error running command: io.appium.uiautomator2.common.exceptions.StaleElementReferenceException: Cached elements ‘By.xpath: //*[contains(@content-desc, ‘answerItem’)]’ do not exist in DOM anymore

[W3C (dd989c97)] at io.appium.uiautomator2.model.ElementsCache.restore(ElementsCache.java:74)

[W3C (dd989c97)] at io.appium.uiautomator2.model.ElementsCache.get(ElementsCache.java:146)

[W3C (dd989c97)] at io.appium.uiautomator2.handler.GetElementAttribute.safeHandle(GetElementAttribute.java:23)

[W3C (dd989c97)] at io.appium.uiautomator2.handler.request.SafeRequestHandler.handle(SafeRequestHandler.java:41)

[W3C (dd989c97)] at io.appium.uiautomator2.server.AppiumServlet.handleRequest(AppiumServlet.java:261)

[W3C (dd989c97)] at io.appium.uiautomator2.server.AppiumServlet.handleHttpRequest(AppiumServlet.java:255)

[W3C (dd989c97)] at io.appium.uiautomator2.http.ServerHandler.channelRead(ServerHandler.java:68)

[W3C (dd989c97)] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366)

[W3C (dd989c97)] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352)

[W3C (dd989c97)] at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:345)

[W3C (dd989c97)] at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102)

[W3C (dd989c97)] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366)

[W3C (dd989c97)] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352)

[W3C (dd989c97)] at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:345)

[W3C (dd989c97)] at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:435)

[W3C (dd989c97)] at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:293)

[W3C (dd989c97)] at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:267)

[W3C (dd989c97)] at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:250)

[W3C (dd989c97)] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366)

[W3C (dd989c97)] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352)

[W3C (dd989c97)] at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:345)

[W3C (dd989c97)] at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:266)

[W3C (dd989c97)] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366)

[W3C (dd989c97)] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352)

[W3C (dd989c97)] at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:345)

[W3C (dd989c97)] at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1294)

[W3C (dd989c97)] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366)

[W3C (dd989c97)] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352)

[W3C (dd989c97)] at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:911)

[W3C (dd989c97)] at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:131)

[W3C (dd989c97)] at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:611)

[W3C (dd989c97)] at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:552)

[W3C (dd989c97)] at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:466)

[W3C (dd989c97)] at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:438)

[W3C (dd989c97)] at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:140)

[W3C (dd989c97)] at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:144)

[W3C (dd989c97)] at java.lang.Thread.run(Thread.java:919)

[W3C (dd989c97)]

[HTTP] <-- GET /wd/hub/session/dd989c97-1fe6-4a96-b034-aed6fe87270b/element/b399e514-7b8c-4d14-a54e-2ce7b149a894/displayed 404 40 ms - 4005

[HTTP]

[HTTP] --> GET /wd/hub/session/dd989c97-1fe6-4a96-b034-aed6fe87270b/element/b399e514-7b8c-4d14-a54e-2ce7b149a894/displayed

[HTTP] {}

This behaviour is expected. What you could do as a workaround is to locate the element right before its visibility should be checked. Also the driver itself could automatically retry the search on the staled element, but this would only happen if this particular element has been found using findElement API. No retry is done if findElements API has been used, because we don’t know how many elements are supposed to be matched (while in the previous case we always know that only one elements is always supposed to be matched).

Thank you @mykola-mokhnach for checking.

@AndroidFindBy(xpath = “//*[contains(@content-desc, ‘answerItem’)]”)
@iOSXCUITFindBy(accessibility = “answerItem”)
public List answerItem;

Aside from moving each android and ios locators values into a variable. Is there a way to retry findElement API?

try replace:

@AndroidFindBy(uiAutomator = "new UiSelector().descriptionContains(\"answerItem\")")

I don’t know any other ways

I changed all pagefactory to pageobject model and used the locator instead of the element as parameter.
Thank you everyone for your help.