You add a button to your page, write the click code, open the browser, and nothing happens. The console says Uncaught TypeError: Cannot read properties of null (reading 'addEventListener'). An addEventListener null error means JavaScript went looking for your button and came back with nothing.
The Problem: An addEventListener null Error
Here is a page that triggers it:
<!DOCTYPE html>
<html>
<head>
<script src="script.js"></script>
</head>
<body>
<button id="sayHi">Say hi</button>
</body>
</html>
const button = document.getElementById("sayHi");
button.addEventListener("click", function () {
alert("Hi!");
});
The id matches. The code looks right. It still fails on line 3.
Why addEventListener Is Called on null
The browser reads your HTML from top to bottom. It reaches the <script> tag in the <head>, stops, and runs the JavaScript right there. At that moment it hasn’t read the body yet. The button doesn’t exist.
When getElementById can’t find an element, it doesn’t raise an error. It quietly returns null. The crash comes one line later, when your code asks null to add a click listener, and null can’t do anything.
Fix 1: Add defer to the Script Tag
<script src="script.js" defer></script>
defer tells the browser to download the file but run it only after the whole page has been read. It’s one word, and it’s the fix I’d reach for first. It only works on scripts loaded with src, not on code written inside the tag.
Fix 2: Move the Script to the End of the Body
<body>
<button id="sayHi">Say hi</button>
<script src="script.js"></script>
</body>
Now the button is already on the page when the script runs.
Fix 3: Wait for DOMContentLoaded
document.addEventListener("DOMContentLoaded", function () {
const button = document.getElementById("sayHi");
button.addEventListener("click", function () {
alert("Hi!");
});
});
This runs your code when the browser has finished reading the HTML, wherever the script tag is.
Still null? Check These
Spelling and capitals.
sayHiandsayhiare different ids.A # that shouldn’t be there.
getElementById("#sayHi")finds nothing. The # belongs toquerySelector.One script shared by two pages. If the button exists on only one of them, the other page gets
null. Wrap the code inif (button) { ... }.
Nearly every addEventListener null error is a timing problem, not a typo. MDN’s script element reference explains defer and its cousin async in detail.
For more practice with buttons and events, try my JavaScript mini projects. And if your calculator says 5 + 5 = 55, that bug has its own post.
Which of the three fixes worked for you? Tell me in the comments, or paste your script tag if it’s still null.
Originally published on my blog. I post new C, Python and AI-agent guides there regularly.

Top comments (0)