A section link whose id is not a valid CSS selector crashes the whole page #231

Closed
opened 2026-09-10 04:13:35 -05:00 by null · 1 comment
Owner

Seen at a25077d (v0.9.5).

What is true now. src/components/ScrollToTop.jsx:9-10 runs document.querySelector(hash). querySelector throws on an id that starts with a digit or is otherwise not a valid selector (/#1, #8x8-...), and the error, thrown in an effect in the root route, replaces the header, page and footer with the error screen.

What it costs. Today a malformed link blanks a page. The long-form pages add section anchors precisely so search results and AI answers can link to them, and two of those sections are about 8x8.

What to do. document.getElementById(decodeURIComponent(hash.slice(1))) inside try/catch; ignore a missing target. The content validator also requires ids that start with a letter.

Verify: loading /services#1 and /#%E0 in a browser leaves the page rendered with no console error, and /contact#contact-form still scrolls to the form.

Seen at a25077d (v0.9.5). **What is true now.** `src/components/ScrollToTop.jsx:9-10` runs `document.querySelector(hash)`. `querySelector` throws on an id that starts with a digit or is otherwise not a valid selector (`/#1`, `#8x8-...`), and the error, thrown in an effect in the root route, replaces the header, page and footer with the error screen. **What it costs.** Today a malformed link blanks a page. The long-form pages add section anchors precisely so search results and AI answers can link to them, and two of those sections are about 8x8. **What to do.** `document.getElementById(decodeURIComponent(hash.slice(1)))` inside try/catch; ignore a missing target. The content validator also requires ids that start with a letter. Verify: loading `/services#1` and `/#%E0` in a browser leaves the page rendered with no console error, and `/contact#contact-form` still scrolls to the form.
null added this to the Batch 18: Guards and landmines found building Batch 17 milestone 2026-09-10 04:13:35 -05:00
null added the
P2
bug
frontend
labels 2026-09-10 04:13:35 -05:00
null closed this issue 2026-09-10 04:34:46 -05:00
Author
Owner

Fixed in b260bca. src/components/ScrollToTop.jsx now uses document.getElementById(decodeURIComponent(hash.slice(1))) inside try/catch instead of document.querySelector(hash). Proven in Chromium against the built site: querySelector('#1') raises a DOMException in that same browser, while /services#1, /#%E0 and /services#8x8-implementation each render with header, footer and h1 present and no page error, and /contact#contact-form still scrolls to the form (scrollY 518). Script: scratchpad/prove-hash.mjs.

Fixed in b260bca. src/components/ScrollToTop.jsx now uses document.getElementById(decodeURIComponent(hash.slice(1))) inside try/catch instead of document.querySelector(hash). Proven in Chromium against the built site: querySelector('#1') raises a DOMException in that same browser, while /services#1, /#%E0 and /services#8x8-implementation each render with header, footer and h1 present and no page error, and /contact#contact-form still scrolls to the form (scrollY 518). Script: scratchpad/prove-hash.mjs.
Sign in to join this conversation.
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: null/Queue-North-Website#231
No description provided.