SharePointVault ~/gotchas/search ⌕ Search 404 pages, error messages, scripts…Ctrl K ★ Star
M↓ README.mdM↓ compare-sharepoint-paths-decode-first.md
sharepoint-vault›gotchas›search›compare-sharepoint-paths-decode-first.mdhistoryedit on GitHub
● GOTCHAsearch· 2 min read

Comparing SharePoint URLs: decode both sides first, then prefix-match on boundaries

applies to: SharePoint Online, SharePoint Serverreviewed: 2026-07-16#search#urls#encoding

Browser URLs are percent-encoded while the search Path comes back decoded, so decode and lowercase both sides first, then prefix-match on a / boundary so /sites/hr can't swallow /sites/hr2.

URL z prohlížeče je procentně kódovaná, ale Path z vyhledávání se vrací dekódovaný – nejdřív obě strany dekóduj a převeď na malá písmena, pak porovnávej prefix na hranici /, aby /sites/hr nepohltilo /sites/hr2.

Symptom

You match search results (or list items) against configured site/library URLs — "is this document under one of the allowed paths?" — and the match never fires, even though the paths are visibly identical on screen.

Cause

The two strings come from different worlds:

  • a URL copied from the browser carries percent-encoding: /sites/HR/Shared%20Documents,
  • the search Path property (and most REST-returned URLs) comes back decoded: /sites/HR/Shared Documents.

Raw startsWith between those two never matches. And once you "fix" it with naive prefixing, a subtler bug appears: /sites/hr happily prefix-matches /sites/hr2.

Fix

Normalize both sides, then compare with a boundary-aware prefix:

const norm = (u: string): string => {
  let s = u;
  try { s = decodeURIComponent(s); } catch { /* already decoded / stray % */ }
  s = s.toLowerCase();
  return s.replace(/\/+$/, '');
};

const isUnder = (path: string, root: string): boolean => {
  const p = norm(path), a = norm(root);
  return p === a || p.indexOf(a + '/') === 0;   // boundary: '/sites/hr' won't match '/sites/hr2'
};

Notes

  • The try/catch around decodeURIComponent matters — a stray % in an already-decoded string throws.
  • Reflex worth adopting: whenever "SharePoint paths don't match", print both raw strings side by side first — the encoding difference is visible instantly and saves an hour of debugging match logic.
  • Unit-test the comparator with real values from both sources (a browser-copied URL and a search Path), not with hand-typed strings — hand-typed test data is always conveniently pre-normalized.
Was this helpful?ask or add your experience on GitHub →
Saved you an hour? A star on GitHub helps other SharePoint people find the vault.★ Star on GitHub
last reviewed: 2026-07-16last updated: 2026-09-24historyedit on GitHubview source