diff --git a/web_src/js/features/repo-code.js b/web_src/js/features/repo-code.js
index 8562ba0072..04cd7b4842 100644
--- a/web_src/js/features/repo-code.js
+++ b/web_src/js/features/repo-code.js
@@ -2,6 +2,9 @@ import $ from 'jquery';
 import {svg} from '../svg.js';
 import {invertFileFolding} from './file-fold.js';
 
+export const singleAnchorRegex = /^#(L|n)([1-9][0-9]*)$/;
+export const rangeAnchorRegex = /^#(L[1-9][0-9]*)-(L[1-9][0-9]*)$/;
+
 function changeHash(hash) {
   if (window.history.pushState) {
     window.history.pushState(null, null, hash);
@@ -114,7 +117,7 @@ export function initRepoCodeView() {
     });
 
     $(window).on('hashchange', () => {
-      let m = window.location.hash.match(/^#(L\d+)-(L\d+)$/);
+      let m = window.location.hash.match(rangeAnchorRegex);
       let $list;
       if ($('div.blame').length) {
         $list = $('.code-view td.lines-code.blame-code');
@@ -124,27 +127,31 @@ export function initRepoCodeView() {
       let $first;
       if (m) {
         $first = $list.filter(`[rel=${m[1]}]`);
-        selectRange($list, $first, $list.filter(`[rel=${m[2]}]`));
+        if ($first.length) {
+          selectRange($list, $first, $list.filter(`[rel=${m[2]}]`));
 
-        // show code view menu marker (don't show in blame page)
-        if ($('div.blame').length === 0) {
-          showLineButton();
+          // show code view menu marker (don't show in blame page)
+          if ($('div.blame').length === 0) {
+            showLineButton();
+          }
+
+          $('html, body').scrollTop($first.offset().top - 200);
+          return;
         }
-
-        $('html, body').scrollTop($first.offset().top - 200);
-        return;
       }
-      m = window.location.hash.match(/^#(L|n)(\d+)$/);
+      m = window.location.hash.match(singleAnchorRegex);
       if (m) {
         $first = $list.filter(`[rel=L${m[2]}]`);
-        selectRange($list, $first);
+        if ($first.length) {
+          selectRange($list, $first);
 
-        // show code view menu marker (don't show in blame page)
-        if ($('div.blame').length === 0) {
-          showLineButton();
+          // show code view menu marker (don't show in blame page)
+          if ($('div.blame').length === 0) {
+            showLineButton();
+          }
+
+          $('html, body').scrollTop($first.offset().top - 200);
         }
-
-        $('html, body').scrollTop($first.offset().top - 200);
       }
     }).trigger('hashchange');
   }
diff --git a/web_src/js/features/repo-code.test.js b/web_src/js/features/repo-code.test.js
new file mode 100644
index 0000000000..0e0062a787
--- /dev/null
+++ b/web_src/js/features/repo-code.test.js
@@ -0,0 +1,17 @@
+import {singleAnchorRegex, rangeAnchorRegex} from './repo-code.js';
+
+test('singleAnchorRegex', () => {
+  expect(singleAnchorRegex.test('#L0')).toEqual(false);
+  expect(singleAnchorRegex.test('#L1')).toEqual(true);
+  expect(singleAnchorRegex.test('#L01')).toEqual(false);
+  expect(singleAnchorRegex.test('#n0')).toEqual(false);
+  expect(singleAnchorRegex.test('#n1')).toEqual(true);
+  expect(singleAnchorRegex.test('#n01')).toEqual(false);
+});
+
+test('rangeAnchorRegex', () => {
+  expect(rangeAnchorRegex.test('#L0-L10')).toEqual(false);
+  expect(rangeAnchorRegex.test('#L1-L10')).toEqual(true);
+  expect(rangeAnchorRegex.test('#L01-L10')).toEqual(false);
+  expect(rangeAnchorRegex.test('#L1-L01')).toEqual(false);
+});