# Spot the bug - #96: Todo List Counter

**URL:** <https://forum.kirupa.com/t/spot-the-bug-96-todo-list-counter/682720>\
**Category:** web dev\
**Created:** [July 24, 2026, 7:00am UTC](https://forum.kirupa.com/t/spot-the-bug-96-todo-list-counter/682720 "2026-07-24T07:00:08Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Ellen1979](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/ellen1979/32/31260_2.png) [@Ellen1979](https://forum.kirupa.com/u/Ellen1979)\
**Post date:** [July 24, 2026, 7:00am UTC](https://forum.kirupa.com/t/spot-the-bug-96-todo-list-counter/682720/1 "2026-07-24T07:00:08Z")

</div>

DOM bug, pretty sneaky.

```js
const items = document.querySelector('.todo li');
console.log(items.length);

```

Reply with what is broken and how you would fix it.

---

<div class="post-metadata">

**Author:** ![kirupa](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/kirupa/32/11616_2.png) [@kirupa](https://forum.kirupa.com/u/kirupa)\
**Post date:** [July 24, 2026, 3:35pm UTC](https://forum.kirupa.com/t/spot-the-bug-96-todo-list-counter/682720/2 "2026-07-24T15:35:09Z")

</div>

querySelector only returns a single item 🙂

---

<div class="post-metadata">

**Author:** ![emmawalter5](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/emmawalter5/32/33266_2.png) [@emmawalter5](https://forum.kirupa.com/u/emmawalter5)\
**Post date:** [July 25, 2026, 7:21am UTC](https://forum.kirupa.com/t/spot-the-bug-96-todo-list-counter/682720/3 "2026-07-25T07:21:47Z")

</div>

`querySelector()` returns **one element** , not a collection, so `.length` doesn’t exist.

**Fix:**

```auto

```

```auto
const items = document.querySelectorAll('.todo li');
console.log(items.length);

```

If you only need the first `<li>`, use `querySelector()` without `.length`.

---

<div class="post-metadata">

**Author:** ![VaultBoy](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/vaultboy/32/31832_2.png) [@VaultBoy](https://forum.kirupa.com/u/VaultBoy)\
**Post date:** [July 25, 2026, 4:20pm UTC](https://forum.kirupa.com/t/spot-the-bug-96-todo-list-counter/682720/4 "2026-07-25T16:20:17Z")

</div>

Caught this exact thing during QA once, `. length` didn’t error out, it just came back undefined and the check silently passed like everything was fine. Kirupa’s site actually has a decent breakdown of querySelector vs querySelectorAll if anyone wants to go deeper on this.

---

<div class="post-metadata">

**Author:** ![Sock](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/sock/32/33811_2.png) [@Sock](https://forum.kirupa.com/u/Sock)\
**Post date:** [July 25, 2026, 4:33pm UTC](https://forum.kirupa.com/t/spot-the-bug-96-todo-list-counter/682720/5 "2026-07-25T16:33:22Z")

</div>

you can’t use “.length” on variables only arrays?

---

<div class="post-metadata">

**Author:** ![Ellen1979](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/ellen1979/32/31260_2.png) [@Ellen1979](https://forum.kirupa.com/u/Ellen1979)\
**Post date:** [July 25, 2026, 4:33pm UTC](https://forum.kirupa.com/t/spot-the-bug-96-todo-list-counter/682720/6 "2026-07-25T16:33:33Z")

</div>

Length isn’t the issue. Strings have `. length` too, so does an array. It’s that `querySelector` hands you back a single DOM element object, and elements don’t have that property at all. I found a related Kirupa article that can help you go deeper into this topic:

. htm

---

<div class="post-metadata">

**Author:** ![kirupa](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/kirupa/32/11616_2.png) [@kirupa](https://forum.kirupa.com/u/kirupa)\
**Post date:** [July 25, 2026, 4:42pm UTC](https://forum.kirupa.com/t/spot-the-bug-96-todo-list-counter/682720/7 "2026-07-25T16:42:40Z")

</div>

@Sock - welcome to the forums! 🙂

---

<div class="post-metadata">

**Author:** ![VaultBoy](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/vaultboy/32/31832_2.png) [@VaultBoy](https://forum.kirupa.com/u/VaultBoy)\
**Post date:** [July 25, 2026, 6:20pm UTC](https://forum.kirupa.com/t/spot-the-bug-96-todo-list-counter/682720/8 "2026-07-25T18:20:08Z")

</div>

welcome @Sock, glad to have you here! plenty of bugs to squash in this thread if you’re looking to warm up lol

---

<div class="post-metadata">

**Author:** ![Ellen1979](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/ellen1979/32/31260_2.png) [@Ellen1979](https://forum.kirupa.com/u/Ellen1979)\
**Post date:** [July 26, 2026, 8:00am UTC](https://forum.kirupa.com/t/spot-the-bug-96-todo-list-counter/682720/9 "2026-07-26T08:00:14Z")

</div>

**Spot the Bug answer:** querySelector returns only a single element, not a list, so items.length is undefined instead of the count of matching li elements

**The fix:**

```js
const items = document.querySelectorAll('.todo li');

```

**Why:**  
querySelector returns the first matching element or null, which has no length property. querySelectorAll returns a NodeList of all matches, which does have a length property, so that is what should be used when you need a count.

* * *

**Got it:** @kirupa, @emmawalter5

**First:** @kirupa 🏆

**Close but not quite:**

@Sock - Misdiagnoses the issue as a general rule about variables vs arrays instead of identifying that querySelector returns a single element/null lacking a length property.
