remix-run/remix · error · TypeError

basePath must be a string

Error message

basePath must be a string

What it means

The asset server's `basePath` option must be a string (it is normalized and default-corrected to `/`). This error fires at option-normalization time when a non-string value such as `null`, a number, or `undefined` sneaks in from an env var or config file.

Source

Thrown at packages/assets/src/lib/asset-server.ts:1139

    throw new TypeError('hmr must create an object')
  }
  if (!('url' in channel) || typeof channel.url !== 'string') {
    throw new TypeError('hmr must create a channel with a string url')
  }
  if (!('close' in channel) || typeof channel.close !== 'function') {
    throw new TypeError('hmr must create a channel with a close function')
  }
  if (!('onFileEvents' in channel) || typeof channel.onFileEvents !== 'function') {
    throw new TypeError('hmr must create a channel with an onFileEvents function')
  }
  if (!('updateWatchedFiles' in channel) || typeof channel.updateWatchedFiles !== 'function') {
    throw new TypeError('hmr must create a channel with an updateWatchedFiles function')
  }
}

function normalizeBasePath(basePath: string): string {
  if (typeof basePath !== 'string') {
    throw new TypeError('basePath must be a string')
  }

  return normalizePathname(basePath || '/').replace(/\/+$/, '') || '/'
}

function normalizeFingerprintOptions(options: {
  fingerprint: AssetServerOptions['fingerprint']
  watch: AssetServerOptions['watch']
}):
  | {
      enabled: false
      buildId?: string
    }
  | {
      enabled: true
      buildId: string
    } {
  if (!options.fingerprint) {

View on GitHub (pinned to 9696913134)

Solutions

  1. Default the value: `basePath: env.BASE_PATH ?? '/'`
  2. If it comes from user config, validate/coerce to string before passing it to the asset server
  3. Check for accidental `null` assignment in config merge/spread logic

Example fix

// before
basePath: process.env.ASSET_BASE_PATH
// after
basePath: process.env.ASSET_BASE_PATH ?? '/'
Defensive patterns

Strategy: type-guard

Validate before calling

let basePath: string = typeof rawBasePath === 'string' ? rawBasePath : '/'

Type guard

function isBasePath(v: unknown): v is string {
  return typeof v === 'string'
}

Prevention

When it happens

Trigger: Passing `basePath: undefined`/`null`/non-string to the asset server options, e.g. `basePath: process.env.BASE_PATH` when the env var is unset or parsed as a number.

Common situations: Reading `basePath` from an environment variable without a fallback; YAML/TOML configs coercing values; spreading a partial config where `basePath` was explicitly set to null.

Related errors


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