remix-run/remix · error · CreateHrefError

missing-hostname

Error message

missing-hostname

What it means

When generating an href from a route pattern, the pattern includes an origin component (port or protocol requiring a host) but the pattern itself has no hostname segment, so there is nothing to fill the hostname from. createHref refuses to build a URL like `https://:8080/...` with an empty host.

Source

Thrown at packages/route-pattern/src/lib/href.ts:86

  ...args: CreateHrefArgs<source>
): string {
  pattern = typeof pattern === 'string' ? RoutePattern.parse(pattern) : pattern
  let patternParts = pattern._parts
  let [params, options] = args

  let hasOrigin =
    patternParts.protocol !== null || patternParts.hostname !== null || patternParts.port !== null
  let result = ''
  let targetOrigin: string | undefined

  if (hasOrigin) {
    let protocol =
      patternParts.protocol === null || patternParts.protocol === 'http(s)'
        ? 'https'
        : patternParts.protocol

    if (patternParts.hostname === null) {
      throw new CreateHrefError({ type: 'missing-hostname', pattern })
    }
    let hostname = hrefPart(pattern, patternParts.hostname, params ?? {})

    let port = patternParts.port === null ? '' : `:${patternParts.port}`
    targetOrigin = `${protocol}://${hostname}${port}`
    result += targetOrigin
  }

  let pathname = hrefPart(pattern, patternParts.pathname, params ?? {})
  pathname = '/' + pathname
  result += pathname

  let search = hrefSearch(patternParts.search, options?.searchParams)
  let searchSuffix = search === undefined ? '' : `?${search}`
  result += searchSuffix

  if (options?.baseURL !== undefined) {
    let baseURL = new URL(options.baseURL)

View on GitHub (pinned to 9696913134)

Solutions

  1. Add a hostname to the pattern: `https://example.com:8080/users/:id`
  2. Or use a wildcard/splat hostname if any host should match: `https://\*:8080/...`
  3. Or drop the port/protocol so the pattern is pathname-only
  4. Write a test that builds hrefs for every registered pattern to catch malformed ones early

Example fix

// before
let pattern = parseRoutePattern('https://:8080/users/:id')

// after
let pattern = parseRoutePattern('https://example.com:8080/users/:id')
Defensive patterns

Strategy: validation

Validate before calling

let pattern = parseRoutePattern(source)
if (pattern.hostname === null && (pattern.port !== null || pattern.protocol !== null)) {
  // refuse before calling href
}

Type guard

null

Try / catch

try { href(pattern, params) } catch (e) { if (e?.type === 'missing-hostname') { /* rebuild pattern with host */ } }

Prevention

When it happens

Trigger: Calling href/createHref with a pattern that has a port or non-wildcard protocol but no hostname span (e.g. a pattern like `https://:8080/users` or one where the hostname is null), or a pattern string that parsed to hostname: null while other origin parts exist.

Common situations: Constructing pattern strings by concatenation and forgetting the host; refactoring patterns from pathname-only to full-URL and leaving an incomplete literal; using a constant port without a host placeholder.

Related errors


AI-assisted analysis of remix-run/remix@9696913134 (2026-08-27). Data as JSON: /api/errors/a9037ab1d8658b17. Report an issue: GitHub.