What the error means
In TypeError: Cannot read properties of null (reading 'addEventListener'), the value to the left of .addEventListener was null. The code expected an object and got nothing.
Browser APIs return null when there is no result: getElementById and querySelector with no match, closest() with no ancestor, match() with no match, and localStorage.getItem() for a missing key. JSON can carry null but never undefined, so API fields fail this way too.
| Where | Message |
|---|---|
| Chrome, Edge, Node.js | TypeError: Cannot read properties of null (reading 'addEventListener') |
| Firefox | TypeError: can't access property "addEventListener", button is null |
| Safari | TypeError: null is not an object (evaluating 'button.addEventListener') |
Common causes
- document.getElementById() or querySelector() matched nothing: a typo in the selector, or the element is on another page.
- The script runs before the element exists, for example a classic script in the head without defer.
- A React ref is read during render, before mount, or after unmount, when ref.current is null.
- A regular expression did not match: "abc".match(/\d+/) returns null, so match[0] fails.
- The API returned null for a field or relation that the UI treats as always present.
Reproduce it
Query an element before it is in the DOM, then use the result.
// Runs before <button id="save"> is parsedconst button = document.getElementById("save"); // nullbutton.addEventListener("click", saveDraft);// TypeError: Cannot read properties of null (reading 'addEventListener')Fix it
Run DOM code after the element exists
Load the script with defer or type="module", or wait for DOMContentLoaded. Then check the result, because the element may not be on every page.
TypeScriptdocument.addEventListener("DOMContentLoaded", () => { const button = document.getElementById("save"); if (!button) return; // this page has no save button button.addEventListener("click", saveDraft);});Read React refs in effects and handlers
React sets ref.current after the element mounts and clears it on unmount. Read it in useEffect or an event handler, never during render.
TypeScriptconst inputRef = useRef<HTMLInputElement>(null); useEffect(() => { inputRef.current?.focus(); // set after mount}, []);Check results that can be null
Treat match(), getItem(), and closest() as maybe-null, and choose a fallback before you use the value.
TypeScriptconst match = orderRef.match(/\d+/);const orderId = match ? Number(match[0]) : null; const saved = localStorage.getItem("draft");const draft = saved ? JSON.parse(saved) : { title: "" };
Catch it in production
The Squasher browser SDK sends this error to your project when it happens, so you do not wait for a user to report it.
- Uncaught errors are captured with the stack frames, page URL, release, and session ID.
- Session replay is on by default in the browser SDK, and replays share the session ID with errors, so you can see whether the element was on screen.
- Call setTag with the page or feature name, so each event says where the element was missing.
import { init, setTag } from "@squasher-ai/browser"; init({ apiKey: import.meta.env.VITE_SQUASHER_API_KEY, projectId: import.meta.env.VITE_SQUASHER_PROJECT_ID, release: import.meta.env.VITE_GIT_SHA, replay: { enabled: true, sampleRate: 0.1 },}); setTag("page", "editor");TypeError: Cannot read properties of null (reading 'addEventListener')
TypeError
- Events
- 86
- First seen
- 1d ago
- Last seen
- 12m ago
- Environment
- production
- Service
- editor-web
Example code and issue.


