remix-run/remix · error · CreateHrefError

nameless-wildcard

Error message

nameless-wildcard

What it means

While serializing a pattern part, an unnamed splat/wildcard token (`*`) had no matching param value. Because the wildcard is nameless it cannot be silently skipped like a named optional param — emitting nothing would change the shape ambiguously — so href construction fails with a nameless-wildcard error.

Source

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

      continue
    }
    if (token.type === '(') {
      stack.push({ begin: i, href: '' })
      i += 1
      continue
    }
    if (token.type === ')') {
      let frame = stack.pop()!
      stack[stack.length - 1].href += frame.href
      i += 1
      continue
    }
    if (token.type === ':' || token.type === '*') {
      let value = params[token.name]
      if (value == null) {
        if (stack.length <= 1) {
          if (token.name === '*') {
            throw new CreateHrefError({ type: 'nameless-wildcard', pattern })
          }
          if (!missingParams.includes(token.name)) missingParams.push(token.name)
          i += 1
          continue
        }
        let frame = stack.pop()!
        i = part.optionals.get(frame.begin!)! + 1
        if (
          stack[stack.length - 1].href.endsWith(separator) &&
          part.tokens[i]?.type === 'separator'
        ) {
          i += 1
        }
        continue
      }
      // oxfmt-ignore
      stack[stack.length - 1].href +=
        part.type === 'pathname' && token.type === ':' ? encodePathnameVariableParam(pattern, token.name, value) :

View on GitHub (pinned to 9696913134)

Solutions

  1. Pass the wildcard value: href(pattern, { '*': 'some/path' })
  2. Or use a named splat in the pattern (`files/*rest`) and pass `rest`
  3. If the wildcard is optional in practice, wrap it in parentheses so it can be skipped

Example fix

// before
href(parseRoutePattern('/files/*'), {})

// after
href(parseRoutePattern('/files/*'), { '*': 'a/b.txt' })
Defensive patterns

Strategy: validation

Validate before calling

let pattern = parseRoutePattern(source)
let needsSplat = pattern.pathname.tokens.some(t => t.type === '*')
if (needsSplat && params['*'] == null) params = { ...params, '*': '' } // or skip link

Type guard

null

Try / catch

try { href(pattern, params) } catch (e) { if (e?.type === 'nameless-wildcard') { /* supply '*' param */ } }

Prevention

When it happens

Trigger: Calling href/pathname building on a pattern containing a bare `*` token (e.g. `files/*`) without supplying a value under the key '*' (params['*']), when that token is not inside an optional segment that could absorb the omission.

Common situations: Copying pattern syntax from a router that uses bare `*` for catch-alls and forgetting params: { '*': 'rest' }; refactoring from named splats to bare ones; omitting catch-all params when deep-linking programmatically.

Related errors


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