Why am I having a stale element reference in this part of my code?

in my system I have to add elements. After I do this, I need to validate them. The things is tthat there is a group of element that are validated in a different way. To solve that I do the next thing:

WebUI.callTestCase(findTestCase('9-Validacion 2'), [:], FailureHandling.STOP_ON_FAILURE)

WebUI.delay(3)
String ExpectedValue = 'BACTE'

WebDriver driver; 
driver = DriverFactory.getWebDriver()
//WebElement Table = driver.findElement(By.xpath('//div/div/div/div/div/div/div/div[3]/div/div'))
WebElement Table = driver.findElement(By.id('Grid1ContainerTbl'))
//Grid1ContainerTbl

List<WebElement> Rows = Table.findElements(By.tagName('tr'))
println(Rows.size())

//List<WebElement> tr_withImg = Table.findElements(By.xpath('//tr[*//img[contains(@id, \'vMODIFICAR_\')]]'))
//List<WebElement> Cols = tr_withImg.get(tr_withImg.size() - 1).findElements(By.tagName('td'))
for (int i = 0; i < Rows.size(); i++) {
    List<WebElement> Cols = Rows.get(i).findElements(By.tagName('td'))
    for (int j = 0; j < Cols.size(); j++) {
        if (Cols.get(j).getText().equalsIgnoreCase(ExpectedValue)) {
			println(Cols.get(j).getText())
			WebUI.delay(3)
			WebUI.callTestCase(findTestCase('9-ValidacionMicroBiologia 3'), [:], FailureHandling.STOP_ON_FAILURE)
        }else{
			WebUI.delay(3)
			WebUI.callTestCase(findTestCase('9-ValidacionNormal 3'), [:], FailureHandling.STOP_ON_FAILURE)
		}
    }
}

The problem with this is that each TC I call works correctly but whenever one of them finishes, I encounter this error:
2019-09-16 10:47:22.947 DEBUG testcase.ValidacionAux - 1: if (getText().equalsIgnoreCase(ExpectedValue))
2019-09-16 10:47:22.989 ERROR c.k.katalon.core.main.TestCaseExecutor - :x: Test Cases/ValidacionAux FAILED.
Reason:
org.openqa.selenium.StaleElementReferenceException: stale element reference: element is not attached to the page document
(Session info: chrome=76.0.3809.132)
For documentation on this error, please visit: Exceptions | Selenium
Build info: version: ‘3.141.59’, revision: ‘e82be7d358’, time: ‘2018-11-14T08:25:53’
System info: host: ‘CONSOLIDADORAPT’, ip: ‘192.168.10.81’, os.name: ‘Windows 10’, os.arch: ‘amd64’, os.version: ‘10.0’, java.version: ‘1.8.0_181’
Driver info: com.kms.katalon.selenium.driver.CChromeDriver
Capabilities {acceptInsecureCerts: false, browserName: chrome, browserVersion: 76.0.3809.132, chrome: {chromedriverVersion: 76.0.3809.68 (420c9498db8ce…, userDataDir: C:\Users\guill\AppData\Loca…}, goog:chromeOptions: {debuggerAddress: localhost:57930}, javascriptEnabled: true, networkConnectionEnabled: false, pageLoadStrategy: normal, platform: XP, platformName: XP, proxy: Proxy(), setWindowRect: true, strictFileInteractability: false, timeouts: {implicit: 0, pageLoad: 300000, script: 30000}, unhandledPromptBehavior: dismiss and notify}
Session ID: 83b412a18adedcab0a290d93b7a7c958
at org.openqa.selenium.remote.http.W3CHttpResponseCodec.createException(W3CHttpResponseCodec.java:187)
at org.openqa.selenium.remote.http.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:122)
at org.openqa.selenium.remote.http.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:49)
at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:158)
at org.openqa.selenium.remote.service.DriverCommandExecutor.execute(DriverCommandExecutor.java:83)
at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:552)
at com.kms.katalon.selenium.driver.CChromeDriver.execute(CChromeDriver.java:20)
at org.openqa.selenium.remote.RemoteWebElement.execute(RemoteWebElement.java:285)
at org.openqa.selenium.remote.RemoteWebElement.getText(RemoteWebElement.java:166)
at org.openqa.selenium.WebElement$getText$0.call(Unknown Source)
at ValidacionAux.run(ValidacionAux:42)
at com.kms.katalon.core.main.ScriptEngine.run(ScriptEngine.java:194)
at com.kms.katalon.core.main.ScriptEngine.runScriptAsRawText(ScriptEngine.java:119)
at com.kms.katalon.core.main.TestCaseExecutor.runScript(TestCaseExecutor.java:337)
at com.kms.katalon.core.main.TestCaseExecutor.doExecute(TestCaseExecutor.java:328)
at com.kms.katalon.core.main.TestCaseExecutor.processExecutionPhase(TestCaseExecutor.java:307)
at com.kms.katalon.core.main.TestCaseExecutor.accessMainPhase(TestCaseExecutor.java:299)
at com.kms.katalon.core.main.TestCaseExecutor.execute(TestCaseExecutor.java:233)
at com.kms.katalon.core.main.TestCaseMain.runTestCase(TestCaseMain.java:114)
at com.kms.katalon.core.main.TestCaseMain.runTestCase(TestCaseMain.java:105)
at com.kms.katalon.core.main.TestCaseMain$runTestCase$0.call(Unknown Source)
at TempTestCase1568641402345.run(TempTestCase1568641402345.groovy:21)

2019-09-16 10:47:22.991 INFO  c.k.katalon.core.main.TestCaseExecutor   - END Test Cases/ValidacionAux

I had this problem before but when I had to interact with a button or other elements. I tried using delays or implementing other solutions but nothing works. Any suggestions?

If, at any point, the other test cases that you call cause the DOM to reload, then the Lists of elements that you generated have a strong chance of becoming “stale”.

In your case, it looks like the list of columns:

List<WebElement> Cols = Rows.get(i).findElements(By.tagName('td'))

… becomes stale. Do either the “9-ValidacionMicroBiologia 3” or “9-ValidacionNormal 3”, at any point, cause the page to reload?

Or cause an XHR/Ajax request to retrieve more data from the server?

Whenever I run one of both TC, its runs perfectly. The big problem is when they run on the if condition. For example 9-ValidacionMicroBiologia 3 reloads two or three times before entering to the tc.

This is 9-ValidacionNormal 3 TC
//List tr_withInput = Table.findElements(By.xpath(’//tr[*//input[contains(@id, ‘vRESULTADOVALOR_’)]]’))
WebDriver driver = DriverFactory.getWebDriver()

WebElement Table = driver.findElement(By.id(‘Grid1ContainerTbl’))
//List Rows = Table.findElements(By.tagName(‘tr’))
List tr_withInput = Table.findElements(By.xpath(’//tr[*//input[contains(@id, ‘vRESULTADOVALOR_’)]]’))

table: for (int i = 1; i < tr_withInput.size(); i++) {
TestObject toV = new TestObject()

String objectXpathV = CustomKeywords.'keywordPrueba.CustomFunction.getDynamicObjects'('//input[@id=\'vRESULTADOVALOR_', i)

toV.addProperty('xpath', ConditionType.EQUALS, objectXpathV)

if (WebUI.verifyElementNotPresent(toV, 5, FailureHandling.OPTIONAL)) {
    break
} else {
    WebElement elementPrueba = WebUiCommonHelper.findWebElement(toV, 5)

    String textInsideInputBox = elementPrueba.getAttribute('value')

    if (textInsideInputBox.isEmpty()) {
        CustomKeywords.'keywordPrueba.CustomFunction.clickUsingJS'(toV, 5)

        WebUI.executeJavaScript('arguments[0].value=\'12\'', Arrays.asList(elementPrueba))
    }
}

}

WebUI.delay(3)

CustomKeywords.‘keywordPrueba.CustomFunction.clickUsingJS’(findTestObject(‘Page_Ingreso de Resultado/input_buttonGuardar’),
30)

WebUI.waitForElementVisible(findTestObject(‘Page_Ingreso de Resultado/img_Validar_0001’), 30)

WebUI.delay(3)

CustomKeywords.‘keywordPrueba.CustomFunction.clickUsingJS’(findTestObject(‘Page_Ingreso de Resultado/img_Validar_0001’),
30)

WebUI.waitForElementVisible(findTestObject(‘Page_Ingreso de Resultado/img_Desvalidar’), 30)

WebUI.delay(3)

WebUI.selectOptionByValue(findTestObject(‘Page_Ingreso de Resultado/select_PorPrueba_Aguardar’), ‘T’, false)

WebUI.delay(3)

CustomKeywords.‘keywordPrueba.CustomFunction.clickUsingJS’(findTestObject(‘Page_Ingreso de Resultado/input_buttonGuardar’),
30)

WebUI.delay(3)

//WebUI.callTestCase(findTestCase(‘9-Validacion 2’), [:], FailureHandling.STOP_ON_FAILURE)

CustomKeywords.‘keywordPrueba.CustomFunction.clickUsingJS’(findTestObject(‘Page_Ingreso de Resultado/img_ingresoResMicro’),5)

WebUI.waitForPageLoad(5)

WebUI.delay(3)

WebElement elementPrueba1 = WebUiCommonHelper.findWebElement(findTestObject(‘Page_Ingreso Resultado MicroBiologia/input_Estado_W01450001vRESULTADOCULTIVOVALOR_0001_txtBox’),5)

WebUI.delay(2)

WebUI.executeJavaScript(‘arguments[0].value=‘12’’, Arrays.asList(elementPrueba1))

WebElement elementPrueba2 = WebUiCommonHelper.findWebElement(findTestObject(‘Page_Ingreso Resultado MicroBiologia/input_Estado_W01450001vRESULTADOCULTIVOVALORTEMPORAL_0001_txtBox’),5)

WebUI.delay(2)

WebUI.executeJavaScript(‘arguments[0].value=‘12’’, Arrays.asList(elementPrueba2))

WebUI.scrollToElement(findTestObject(‘Page_Ingreso Resultado MicroBiologia/input_Resultado Observacion_W01450001BTNGUARDAR’), 5)
WebUI.delay(3)
CustomKeywords.‘keywordPrueba.CustomFunction.clickUsingJS’(findTestObject(‘Page_Ingreso Resultado MicroBiologia/input_Resultado Observacion_W01450001BTNGUARDAR’),5)

WebUI.delay(3)

CustomKeywords.‘keywordPrueba.CustomFunction.clickUsingJS’(findTestObject(‘Page_Ingreso Resultado MicroBiologia/img_VALIDAR’),5)

WebUI.delay(3)

Yes exactly. That is your problem. Whenever the page “reloads” (in other words, the DOM is updated in some way), any element references that you have usually become stale. This is because webdriver can no longer guarantee that the elements you located prior to the reload either 1.) still exist, or 2.) have the same attributes after the reload. The solution is usually to re-locate those elements after each iteration of your loops:

List<WebElement> Rows = Table.findElements(By.tagName('tr')) println(Rows.size())
for (int i = 0; i < Rows.size(); i++) {
    List<WebElement> Cols = Rows.get(i).findElements(By.tagName('td'))
    for (int j = 0; j < Cols.size(); j++) {
        if (Cols.get(j).getText().equalsIgnoreCase(ExpectedValue)) {
			println(Cols.get(j).getText())
			WebUI.delay(3)
			WebUI.callTestCase(findTestCase('9-ValidacionMicroBiologia 3'), [:], FailureHandling.STOP_ON_FAILURE)
        }else{
			WebUI.delay(3)
			WebUI.callTestCase(findTestCase('9-ValidacionNormal 3'), [:], FailureHandling.STOP_ON_FAILURE)
		}
        Rows = Table.findElements(By.tagName('tr'))
        Cols = Rows.get(i).findElements(By.tagName('td'))
    }
    Rows = Table.findElements(By.tagName('tr')) 
}

The list that is stale is Rows because even with your solution it gives me the same error and in this part of the TC:
2019-09-17 11:37:55.018 DEBUG testcase.ValidacionAux - 3: Rows = Table.findElements(By.tagName(“tr”))

And that situation is in the case of “9-ValidacionMicroBiologia 3” where I have to click on a certain button located on the same page where I have to find ‘BACTE’ in ValidacionAux TC

In the caase of the other TC, the tc runs then throws the error

Oh, you may need to also relocate the table element. This probably becomes stale as well:

List<WebElement> Rows = Table.findElements(By.tagName('tr')) println(Rows.size())
for (int i = 0; i < Rows.size(); i++) {
    List<WebElement> Cols = Rows.get(i).findElements(By.tagName('td'))
    for (int j = 0; j < Cols.size(); j++) {
        if (Cols.get(j).getText().equalsIgnoreCase(ExpectedValue)) {
			println(Cols.get(j).getText())
			WebUI.delay(3)
			WebUI.callTestCase(findTestCase('9-ValidacionMicroBiologia 3'), [:], FailureHandling.STOP_ON_FAILURE)
        }else{
			WebUI.delay(3)
			WebUI.callTestCase(findTestCase('9-ValidacionNormal 3'), [:], FailureHandling.STOP_ON_FAILURE)
		}
        Table = driver.findElement(By.id('Grid1ContainerTbl'))
        Rows = Table.findElements(By.tagName('tr'))
        Cols = Rows.get(i).findElements(By.tagName('td'))
    }
    Table = driver.findElement(By.id('Grid1ContainerTbl'))
    Rows = Table.findElements(By.tagName('tr')) 
}

Hi,
I am trying to take a different approach to this problem by using a global variable.
I created my variable called sector like this:

Then I have a TC called carga orden that sets the variable like this:
GlobalVariable.sector = WebUI.getText(findTestObject(‘Page_Ingreso Orden/p_Sector’));

Whenever I try to access sector from another TC its empty. For example this simple code does not work for me:
if(GlobalVariable.sector.equals(‘BACTERIOLOGÍA’)){
println(‘Hola’)
}
Am I missing something? Documentation is not clear enough for me.

You have to run the 2 TC on a Test Suite, or call one TC on the other

Yes, thank you. I figured that just now