{"record":{"id":"bc9eaeed293d7377","repo":"tastejs/todomvc","slug":"cannot-determine-what-kind-of-selectors-this-app-u-bc9eae","errorCode":null,"errorMessage":"Cannot determine what kind of selectors this app uses.","messagePattern":"Cannot determine what kind of selectors this app uses\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"cypress/e2e/spec.cy.js","lineNumber":513,"sourceCode":"      }\n      cy.document().then(doc => {\n        if (framework in usesIDSelectors) {\n          setSelectors(usesIDSelectors[framework])\n          createTodoCommands(usesIDSelectors[framework])\n        } else if (findDeep(doc, 'input#new-todo') && findDeep(doc, 'input.new-todo')) {\n          throw new Error(\n            'Cannot determine what kind of selectors this app uses. Add it to usesIDSelectors.'\n          )\n        } else if (findDeep(doc, 'input#new-todo')) {\n          cy.log('app uses ID selectors')\n          setSelectors(true)\n          createTodoCommands(true)\n        } else if (findDeep(doc, 'input.new-todo')) {\n          cy.log('app uses class selectors')\n          setSelectors(false)\n          createTodoCommands(false)\n        } else {\n          throw new Error(\n            'Cannot determine what kind of selectors this app uses.'\n          )\n        }\n      })\n    })\n\n    beforeEach(() => {\n      // catch any framework that debounces its localStorage writes\n      // and causes items to \"appear\" in a new test all of the sudden\n      hasNoItems()\n    })\n\n    afterEach(() => {\n      // to detect when a test queued up some operation\n      // and it happens AFTER test finishes\n      currentTestId = 0\n    })\n","sourceCodeStart":495,"sourceCodeEnd":531,"githubUrl":"https://github.com/tastejs/todomvc/blob/ff43b02e59dfa604386bb382034b2cd07c2bcd8a/cypress/e2e/spec.cy.js#L495-L531","documentation":"Thrown at cypress/e2e/spec.cy.js:513, the final else branch of the same selector-detection block as error 2. It fires when the framework is not in `usesIDSelectors` AND neither `input#new-todo` nor `input.new-todo` can be found anywhere in the document, including inside shadow roots (findDeep walks shadow trees at line 487-495). In practice this means the app never rendered its new-todo input: the page did not load, the build was skipped, the framework threw during boot, or the markup uses a non-standard selector the spec does not recognize.","triggerScenarios":"Cypress visited a URL that returned a 404 or a blank page; the example's build output (dist/) was never produced so baseUrl serves nothing; the framework's JS errored on boot so the input was never created; the app renders the input under a different selector (e.g. a custom element name) that matches neither convention; a timing issue where the document is queried before the framework has hydrated (though `cy.document().then(...)` yields after load, slow hydration can still lose the race).","commonSituations":"Forgot `npm run build` for a build-step framework (angular, react, vue, lit, svelte all land in dist/ per frameworkFolders at line 38); baseUrl or framework folder mapping is wrong so the wrong page loads; a new example with bespoke markup; a framework boot error swallowed by the app but visible as a missing input; shadow-DOM app where findDeep's recursive walk misses a closed shadow root.","solutions":["Confirm the app actually loads: open the same URL Cypress visits in a browser and check the new-todo input is present and focused.","Build the example first (`npm run build` in the framework folder) so dist/ exists for build-step frameworks.","Verify baseUrl in cypress.config.js and the frameworkFolders mapping at line 38 point to the runnable index.html.","If the app legitimately uses a non-standard selector, add the framework to `usesIDSelectors` at line 132 AND extend the idSelectors/classSelectors maps so the chosen style has the right query.","Check the browser console / Cypress command log for a framework boot error that prevented the input from rendering."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Assert the app booted before selector detection runs, so a load failure\n// surfaces as a clear assertion instead of the generic 'cannot determine' throw.\ncy.document().then(doc => {\n  const hasAnyInput = findDeep(doc, 'input')\n  if (!hasAnyInput) {\n    throw new Error(`App at ${Cypress.config('baseUrl')} rendered no <input>; build missing or wrong URL.`)\n  }\n})","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always build the framework (npm run build) before running the spec; build-step frameworks serve from dist/ (see frameworkFolders line 38).","Pin baseUrl in cypress.config.js and smoke-test it with a `cy.visit()` + `cy.get('body')` sanity check in a separate minimal spec.","Add a pre-flight script that curls the app URL and fails if the new-todo input is absent.","If a framework uses a non-standard selector, register it in `usesIDSelectors` and extend the selector maps rather than hoping detection finds it.","Watch for framework boot errors in the browser console — a swallowed exception is the usual cause of a missing input."],"tags":["cypress","app-loading","runtime-detection","selectors","build-step","shadow-dom"],"backgroundTag":null,"analyzedSha":"ff43b02e59dfa604386bb382034b2cd07c2bcd8a","analyzedAt":"2026-08-13T10:00:20.798Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}