remix-run/remix · error · TypeError

${optionPath}.${key} is not a supported target

Error message

${optionPath}.${key} is not a supported target

What it means

Inside the script target object, only known target keys are allowed: `es` plus recognized browser target names (chrome, firefox, safari, etc.). An unrecognized key throws with the offending key name so typos don't silently drop targets.

Source

Thrown at packages/assets/src/lib/target.ts:106

function normalizeScriptTargetObject(
  target: AssetTarget | undefined,
  optionPath: string,
): NormalizedAssetTarget | undefined {
  if (target == null) return undefined
  if (!isPlainObject(target)) {
    throw new TypeError(`${optionPath} must be an object`)
  }

  let normalizedTarget: NormalizedAssetTarget = {}

  for (let [key, value] of Object.entries(target)) {
    if (key === 'es') {
      normalizedTarget.es = normalizeScriptTargetVersion(value, `${optionPath}.es`)
      continue
    }

    if (!browserTargetNameSet.has(key)) {
      throw new TypeError(`${optionPath}.${key} is not a supported target`)
    }

    normalizedTarget[key as BrowserTargetName] = normalizeBrowserTargetVersion(
      value,
      `${optionPath}.${key}`,
    )
  }

  return Object.keys(normalizedTarget).length === 0 ? undefined : normalizedTarget
}

function normalizeStyleTargetObject(
  target: AssetTarget | undefined,
  optionPath: string,
): NormalizedAssetTarget | undefined {
  if (target == null) return undefined
  if (!isPlainObject(target)) {
    throw new TypeError(`${optionPath} must be an object`)

View on GitHub (pinned to 9696913134)

Solutions

  1. Move ES version under the es key: { es: 2022 } instead of { es2022: true }
  2. Remove non-browser keys like node — they are not supported here
  3. Check the BrowserTargetName set in the docs/source for valid key names

Example fix

// before
script: { target: { es2020: true, node: 18 } }
// after
script: { target: { es: 2020, chrome: '100' } }
Defensive patterns

Strategy: validation

Validate before calling

const allowed = new Set(['es', 'chrome', 'firefox', 'safari', 'edge', 'ios', 'node' /* remove if unsupported */])
for (const key of Object.keys(target)) if (!allowed.has(key)) throw new Error('unsupported target: ' + key)

Type guard

function isSupportedTargetKey(key: string): boolean {
  return key === 'es' || browserTargetNameSet.has(key)
}

Prevention

When it happens

Trigger: Passing `{ target: { es2022: true } }`, `{ targt: ... }` typos, or non-browser keys like `{ node: 18 }` in script.target.

Common situations: Copy-pasting target config from esbuild (which accepts names like 'node' or version strings as keys); typos; using an outdated target name after a library update renamed it.

Understand the failure class

Background: Invalid option value errors: "must be one of", "is not a valid", and "only allows" failures explained — this error's family across 23 libraries.

Related errors


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