remix-run/remix · error · TypeError

hmr requires watch mode

Error message

hmr requires watch mode

What it means

`--no-headers` suppresses the header row of the tabular routes output, so it only makes sense alongside `--table`. The parser rejects it in any other mode because there's no header row to suppress.

Source

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

  console.error(error)
}

function resolveAssetServerOptions<transforms extends AssetRequestTransformMap>(
  options: AssetServerCreateOptions<transforms>,
): ResolvedAssetServerOptions<transforms> {
  let rootDir = normalizeFilePath(fs.realpathSync(path.resolve(options.rootDir ?? process.cwd())))
  let basePath = normalizeBasePath(options.basePath)
  let scriptOptions = options.scripts ?? {}
  let fingerprintOptions = normalizeFingerprintOptions({
    fingerprint: options.fingerprint,
    watch: options.watch,
  })
  let watchOptions = normalizeWatchOptions(options.watch)
  let hmrFactory = normalizeHmrFactory(options.hmr)
  let mounts = options.mounts ?? defaultMounts

  if (hmrFactory && watchOptions === null) {
    throw new TypeError('hmr requires watch mode')
  }
  if (Object.keys(mounts).length === 0) {
    throw new TypeError('mounts must include at least one entry')
  }
  return {
    allowFiles: options.allowFiles,
    allowPackages: options.allowPackages,
    basePath,
    buildId: fingerprintOptions.buildId,
    define: scriptOptions.define,
    denyFiles: options.denyFiles,
    external: scriptOptions.external ?? [],
    files: normalizeFilesOptions(options.files),
    fingerprintAssets: fingerprintOptions.enabled,
    hmr: hmrFactory,
    minify: options.minify ?? false,
    mounts,
    loaders: scriptOptions.loaders ?? [],

View on GitHub (pinned to 9696913134)

Solutions

  1. Add `--table`: `remix routes --table --no-headers`
  2. Or remove `--no-headers` if you want default/JSON output

Example fix

# before
remix routes --no-headers
# after
remix routes --table --no-headers
Defensive patterns

Strategy: validation

Validate before calling

let args = ['remix','routes'];
if (table) { args.push('--table'); if (noHeaders) args.push('--no-headers'); }

Type guard

function noHeadersIsValid(f: { table?: boolean; noHeaders?: boolean }): boolean {
  return !f.noHeaders || Boolean(f.table);
}

Prevention

When it happens

Trigger: Running `remix routes --no-headers` without `--table` (e.g. alone or with `--json`) — `noHeaders && !table` triggers the error.

Common situations: Pipelines tuned for headerless table output that later dropped `--table`; combining with `--json` by mistake.

Related errors


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