encode/httpx · error · InvalidURL
Relative URLs cannot have a path starting with '//'
Error message
Relative URLs cannot have a path starting with '//'
What it means
Raised by validate_path when a relative URL (no scheme and no authority) has a path beginning with '//'. Per RFC 3986 §4.2, '//path' would be parsed as an authority, leaving an empty host; rather than silently mis-parsing, httpx rejects it. A leading '//' on a scheme-less URL is almost always a typo or a missing scheme.
Source
Thrown at httpx/_urlparse.py:439
def validate_path(path: str, has_scheme: bool, has_authority: bool) -> None:
"""
Path validation rules that depend on if the URL contains
a scheme or authority component.
See https://datatracker.ietf.org/doc/html/rfc3986.html#section-3.3
"""
if has_authority:
# If a URI contains an authority component, then the path component
# must either be empty or begin with a slash ("/") character."
if path and not path.startswith("/"):
raise InvalidURL("For absolute URLs, path must be empty or begin with '/'")
if not has_scheme and not has_authority:
# If a URI does not contain an authority component, then the path cannot begin
# with two slash characters ("//").
if path.startswith("//"):
raise InvalidURL("Relative URLs cannot have a path starting with '//'")
# In addition, a URI reference (Section 4.1) may be a relative-path reference,
# in which case the first path segment cannot contain a colon (":") character.
if path.startswith(":"):
raise InvalidURL("Relative URLs cannot have a path starting with ':'")
def normalize_path(path: str) -> str:
"""
Drop "." and ".." segments from a URL path.
For example:
normalize_path("/path/./to/somewhere/..") == "/path/to"
"""
# Fast return when no '.' characters in the path.
if "." not in path:
return pathView on GitHub (pinned to b5addb64f0)
Solutions
- Provide a scheme: httpx.URL('https://example.com/path').
- If the URL is intentionally relative, prefix the path with a single '/' or remove the leading slashes.
- Detect protocol-relative strings at input time and prepend a default scheme.
- Use urljoin with a base URL to resolve relative references.
Example fix
// before
url = httpx.URL("//example.com/path") # InvalidURL
// after
url = httpx.URL("https://example.com/path") Defensive patterns
Strategy: validation
Validate before calling
def absolutize(url: str, default_scheme: str = "https") -> str:
if url.startswith("//"):
return f"{default_scheme}:{url}"
return url
url = httpx.URL(absolutize(user_url)) Type guard
def is_protocol_relative(url: str) -> bool:
return url.startswith("//") and not url.startswith("///") Try / catch
from httpx import InvalidURL
try:
url = httpx.URL(maybe_relative)
except InvalidURL as e:
if "cannot have a path starting with '//'" in str(e):
url = httpx.URL("https:" + maybe_relative)
else:
raise Prevention
- Reject or repair protocol-relative URLs at the input boundary.
- Always supply a scheme when constructing httpx.URL objects for requests.
- Use urljoin with a real base URL to resolve relative references.
When it happens
Trigger: httpx.URL('//example.com/path') (no scheme), or httpx.URL(path='//foo').
Common situations: Dropping the 'https:' from a copied URL but keeping '//'; building protocol-relative URLs as httpx.URL objects (they are only valid in HTML context, not as a request target); missing scheme when concatenating.
Related errors
- Relative URLs cannot have a path starting with ':'
- For absolute URLs, path must be empty or begin with '/'
- URL too long
- Invalid non-printable ASCII character in URL, {char!r} at po
- URL component '{key}' too long
AI-assisted analysis of encode/httpx@b5addb64f0 (2026-08-04).
Data as JSON: /data/errors/ca47ea2b3fbbf04a.json.
Report an issue: GitHub.