request.completeUrl contains unencoded spaces
-
What you'll see
A canonical tag, an
og:url, a sitemap entry or aLocationheader comes out containing literal spaces. Browsers often paper over it, so it survives a manual click-through and fails where nothing is watching: crawlers, link checkers, social preview fetchers and anything that compares the canonical against the requested URL.Measured before the fix, on a page stored at
/Test files/zz-inventory.hash:request.completeUrl // https://example.net/Test files/zz-inventory <- spaces request.encodedUrl // https://example.net/Test-files/zz-inventory <- slugifiedThe name reads like the most complete and therefore the most correct option. It is the most complete and the least suitable for output.
-
What's actually happening
There are eight URL members on
request, and they are not eight variations on a theme. They are two axes crossed: raw or slugified, and relative or absolute.Member Value for /Test files/zz-inventory.hashurl,Url/Test-files/zz-inventoryurlpath/Test-files/zz-inventoryrawurl,rawUrl/Test files/zz-inventorycompleteUrlhttps://example.net/Test-files/zz-inventoryencodedUrl,encodedFileUrlhttps://example.net/Test-files/zz-inventorysiteUrlhttps://example.net/The capitalised pairs are aliases, not variants:
urlandUrlcarry the same value, as dorawurlandrawUrl. Either spelling works.The slugified forms are what the site actually serves — a folder named
Test filesis reachable at/Test-files/. The raw forms mirror the names on the drive, and are legitimate for matching against a drive path.completeUrlused to be the exception: until 22 August 2026 it did not slugify folder and file names, and returnedhttps://example.net/Test files/zz-inventory. It is now slugified the same way asencodedUrl. -
What to do
1. Choose by destination, not by name.
You want Use A link, canonical, og:url, sitemap entry orLocationheaderrequest.encodedUrlA site-relative link in markup request.urlThe site root request.siteUrl(request.sitenameis the name of the published folder, not the host)To read or write the file behind this request request.filepath,request.folderpathTo compare against a stored path Pick one family and stay in it — raw or slugified, never a mix 2.
completeUrlandencodedUrlare now encoded the same way, but they are not the same value:completeUrlis the actual request path (plus the query string in API calls), whileencodedUrlis the page's address without a trailing/indexor slash — they differ for the site root, folders and index pages. Older pages that avoidcompleteUrldo not need to change.3. Do not encode it yourself afterwards. Running
completeUrlthrough an encoder produces%20where the site serves a hyphen, so the result is a valid URL that resolves to nothing. The slug is a rename, not an escape. See Do not build file and image URLs by hand.4. Do not reach for
hostordomain. They arenull, and because an unresolved or null name renders as an empty string rather than raising, a template that uses one produces a URL missing its host with no error anywhere. See Unresolved names in hash expressions render empty.5. Print the members rather than guessing between them. Which one you have is a one-request question — see Use a scratch hash file to test Docly functions.
Last reviewed 21 Aug 2026