Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

2.3K
Views
Why is Cypress saying my element is detached after just running a get command?

Objective: I want to click on a particular element on the page using an accessibility selector with cypress

Code

cy.findAllByRole('rowheader').eq(2).click();

Error

Timed out retrying: cy.click() failed because this element is detached from the DOM.

<th scope="row" data-automation-id="taskItem" aria-invalid="false" tabindex="-1" class="css-5xw9jq">...</th>

Cypress requires elements be attached in the DOM to interact with them.

The previous command that ran was:

  > cy.eq()

This DOM element likely became detached somewhere between the previous and current command.

Question: I can see in the DOM that this element is still present - there is no logic that will detach this element from the DOM, and the eq method certainly wouldn't do that. Additionally, the findAllByRow method is clearly working as it has found the correct th element I want to click on. How come its saying the element is detached? Is there a workaround for this situation?

over 4 years ago · Santiago Trujillo
9 answers
Answer question

0

The answer to your question is written in the error message that you got:

Timed out retrying: cy.click() failed because this element is detached from the DOM.

...

Cypress requires elements be attached in the DOM to interact with them.

The previous command that ran was:

cy.eq()

This DOM element likely became detached somewhere between the previous and current command.

Getting this error means you've tried to interact with a "dead" DOM element - meaning it's been detached or completely removed from the DOM. So by the time, cypress is about to click the element eq() was either detached or removed from the DOM.

In modern JavaScript frameworks, DOM elements are regularly re-rendered - meaning that the old element is thrown away and a new one is put in its place. Because this happens so fast, it may appear as if nothing has visibly changed to the user. But if you are in the middle of executing test commands, it's possible the element you're interacting with has become "dead". To deal with this situation you must:

  • Understand when your application re-renders
  • Re-query for newly added DOM elements
  • Guard Cypress from running commands until a specific condition is met

When we say guard, this usually means:

  • Writing an assertion
  • Waiting on an XHR

You can read more from cypress docs and from the official cypress blog.

Solution: Make sure your elements are loaded and visible first and then perform the click()

cy.findAllByRole('rowheader').eq(2).should('be.visible').click();
over 4 years ago · Santiago Trujillo Report

0

I'm running in the same issue, get the same error while running:

cy.get('<elementId>').should('be.visible').click();

I can see as the test runs that it finds the element (and highlights it), the assertion is validated and then somehow the .click() fails to find the element even though it is chained.

I found that adding a static wait before this line for a couple seconds addresses the issue, but I am not sure why I would need to do that and don't really want to use a static wait.

There are no asynchronous tasks running so there is no way to do a dynamic wait.

over 4 years ago · Santiago Trujillo Report

0

Without a reproducible example, it's speculative, but try adding a guard before the click using Cypress.dom.isDetached

cy.findAllByRole('rowheader').eq(2)
  .should($el => {
    expect(Cypress.dom.isDetached($el).to.eq(false)
  })   
  .click()

If the expect fails, then a prior line is causing the detach and cy.findAllByRole is not re-querying the element correctly.

If so you might be able to substitute a plain cy.get().


I also like @AntonyFuentesArtavia idea of using an alias, because the alias mechanism saves the original query and specifically requeries the DOM when it finds it's subject is detached.

See my answer here

From the Cypress source

const resolveAlias = () => {
  // if this is a DOM element
  if ($dom.isElement(subject)) {
    let replayFrom = false

    const replay = () => {
      cy.replayCommandsFrom(command)

      // its important to return undefined
      // here else we trick cypress into thinking
      // we have a promise violation
      return undefined
    }

    // if we're missing any element
    // within our subject then filter out
    // anything not currently in the DOM
    if ($dom.isDetached(subject)) {
      subject = subject.filter((index, el) => $dom.isAttached(el))

      // if we have nothing left
      // just go replay the commands
      if (!subject.length) {
        return replay()
      }
    }
over 4 years ago · Santiago Trujillo Report

0

This happens because React rerenders the whole page. Try to find element with one command:

// do this
cy.get('[role="rowheader"]:nth-ckild(2)').click();

// instead of this
cy.findAllByRole('rowheader').eq(2).should('be.visible').click();

Using a single command fixes the fact that Cypress retries only the last command before the should command. So, previously, only the .eq(2) will be retried. Whereas, you need cy.findAllByRole('rowheader') to be retried too.

Cypress suggests another solution of alternating commands and assertions. It didn't work for me but you can try it:

cy.findAllByRole('rowheader').should('be.visible').eq(2).should('be.visible').click();
over 4 years ago · Santiago Trujillo Report

0

Here is something that helped me to avoid that detached issue. Using Cypress aliases and the built-in assertion retry-ability.

Example:

cy.get('some locator').first().find('another locator').eq(1).as('element');
cy.get('@element').should(***some assertion to be retried until met***);

So even though I'm traversing a bunch of elements (which could lead to problems because one of the parents could potentially get detached), in the end when I put an alias on top of it, I'm adding a direct link to the final element that was yielded at the end of the chain. Then when I refer to that alias Cypress will re-query the final element and retry it as needed based on any assertions added on top of it. Which indeed helped me a lot to prevent that detached problem.

over 4 years ago · Santiago Trujillo Report

0

This could be bad advice, but can you try the following?

cy.findAllByRole('rowheader').eq(2).click({force: true})
over 4 years ago · Santiago Trujillo Report

0

Couldn't edit "Ε Г И І И О"'s answer as the edit queue is full, but i think it's important to complement the answer for future learners.

cy.findAllByRole('rowheader').eq(2).click({force: true})

Using { force: true } on click works due to the nature of cypress. According to their documentation the argument force "Forces the action, disables waiting for actionability".

As for "waiting for actionability", it references the assertions section that states:

  • .click() will automatically wait for the element to reach an actionable state
  • .click() will automatically retry until all chained assertions have passed

So this basically disables the above, and that's why it works. One will probably find this useful in some libraries/frameworks that manages the website rendering (like React and Angular).

over 4 years ago · Santiago Trujillo Report

0

I am getting the same problem as per the question title during a cypress test, which tries to click on a particular option from a drop-down list.

During the test, it clicks on this drop-down menu element, and then, it tries to get the required option from it.

I applied some asserting suggestions provided here as mentioned below. All of them got passed, but the option from the drop-down list, which I wanted to get clicked wasn't performed during the test.

  • wait(5000)
  • should($item => { expect(Cypress.dom.isDetached($item)).to.equal(false); })
  • should('be.visible')
  • click({ force: true })

Still, the test gives me the same error as before. Any kind assistance here from anyone?

over 4 years ago · Santiago Trujillo Report

0

I was getting this error when I was using below statement: cy.wrap($e1).click() Then the below statement worked for me: $e1.click() worked for me without using any wrap method.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!