Project page fails to load due to read_more.js SyntaxError when anchor links to multibyte README heading
Everyone can contribute. Help move this issue forward while earning points, leveling up and collecting rewards.
Summary
When an anchor link points to a header in the project README preview that contains multibyte characters (e.g., Japanese), the GitLab project page fails to complete rendering.
This is due to an uncaught SyntaxError in read_more.js.
Steps to reproduce
- Create a project with a project description and a README that includes a multibyte-character heading, such as
## 日本語. - On the project’s overview page, click the anchor link in the README preview that points to that heading.
- Observe that the page gets stuck in a loading state and does not render the content.
Example Project
https://gitlab.com/monkey36/check-readme-anchor-error
What is the current bug behavior?
The page fails to load completely after clicking the anchor link. In the browser's developer console, the following error appears:
read_more.js:43 Uncaught SyntaxError: Failed to execute 'querySelector' on 'Element': '#user-content-%E6%97%A5%E6%9C%AC%E8%AA%9E' is not a valid selector.
at read_more.js:43:46
at NodeList.forEach (<anonymous>)
at o (read_more.js:27:14)
at Module.tGlJ (index.js:9:1)
at r (bootstrap:101:22)
at 324 (pages.projects.show.1baaf8d8.chunk.js:1:2259)
at r (bootstrap:101:22)
at c (bootstrap:45:15)
at Array.a [as push] (bootstrap:32:11)
at pages.projects.show.1baaf8d8.chunk.js:1:43
What is the expected correct behavior?
The anchor should correctly scroll to the specified section, and the page should load normally, even if the heading contains multibyte characters like Japanese.
Relevant logs and/or screenshots
readme_load_error_2025-08-03_002043
Output of checks
This bug happens on GitLab.com
Implementation guide
In read_more.js, the following line causes the issue:
const hashTargetEl = readMoreContent.querySelector(`#user-content-${targetId}`);
This could be fixed by using CSS.escape():
const hashTargetEl = readMoreContent.querySelector(`#user-content-${CSS.escape(targetId)}`);
This would ensure valid CSS selectors even when the id contains multibyte or special characters.
I'm still a beginner in JavaScript, so I haven't tested this fix myself—apologies if it’s incorrect, but I hope it helps point in the right direction.