## TL;DR
Somewhere your app code calls `setAttribute` on an element lookup that returned null, and it only happens headless because headless timing shifts when the element appears. Find the line from the stack trace, wait for the element to exist before the code touches it (or guard the lookup and throw a clear error), and the TypeError disappears. Do not just retry the test until it passes.

```text
cypress "Cannot read properties of null (reading 'setAttribute')" only in headless CI runs
```

## Steps
1. Open the CI failure and copy the stack trace. Find the first frame in your own code (not in Cypress internals) that calls `setAttribute`. Expected: you have the file and line where the null element is used.
2. Read the lookup just above it (a querySelector, getElementById, or framework ref). Ask why it can return null at that moment: the element renders after an async fetch, after a route change, or after a conditional branch. Expected: you can name the race.
3. Make the code wait for the element instead of assuming it: await the data or the render condition before touching the DOM, or move the `setAttribute` call into the callback that creates the element. Expected: the lookup cannot run before the element exists.
4. As a backstop, guard the lookup so a future miss throws your own clear error naming the element instead of the cryptic null TypeError. Expected: any regression fails with a message you can act on.
5. Rerun the spec headless several times in CI. Expected: no TypeError across the runs.

## Use this when
- App code throws "reading 'setAttribute'" on null only in headless CI
- The stack trace points at your code, not at a Cypress command
- The same spec passes headed or locally

## Not for this skill when
- A Cypress command itself cannot find the element (fix the selector or the wait)
- The error happens headed too (plain bug, not a headless timing issue)
- The null comes from an API response, not the DOM (that is a data problem)

## Variant phrasings
- cypress setAttribute of null headless only
- cannot read properties of null in cypress CI
- cypress headless timing element null error

## Why it happens
Headless Chrome runs on a different timing profile than headed: rendering, font loading, and animation frames interleave differently, so an element your code expects synchronously may not be in the DOM yet. Locally the timing usually lines up by luck. The null is not a Cypress bug; it is app code racing the render.

## Edge cases
- If the element only exists on some routes, the guard should handle "element legitimately absent" as a separate case from "element not yet rendered".
- Framework refs (React ref, Vue ref) can be null during the same window; the same wait-then-touch ordering applies.
- If you cannot reproduce headless locally, run the single spec with the CI viewport size; small viewports change what renders and when.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_PEu8e3XToeA8_smtxTIjCA
