remix-run/remix · error · TypeError

${optionPath} must include at least one extension

Error message

${optionPath} must include at least one extension

What it means

Extension lists such as `files.transformExtensions` cannot be empty arrays — at least one extension is required for the option to be meaningful. An explicit `[]` is treated as a configuration mistake rather than 'none'.

Source

Thrown at packages/assets/src/lib/files/config.ts:325

    cache: files.cache,
    extensions: normalizedExtensions,
    globalTransforms: normalizedGlobalTransforms,
    hasTransforms: normalizedTransforms.size > 0 || normalizedGlobalTransforms.length > 0,
    maxRequestTransforms,
    transforms: normalizedTransforms,
  }
}

function normalizeTransformExtensions(
  extensions: readonly string[] | undefined,
  optionPath: string,
): readonly string[] | undefined {
  if (extensions === undefined) return undefined
  if (!Array.isArray(extensions)) {
    throw new TypeError(`${optionPath} must be an array`)
  }
  if (extensions.length === 0) {
    throw new TypeError(`${optionPath} must include at least one extension`)
  }

  let normalizedExtensions: string[] = []
  let seen = new Set<string>()

  for (let extension of extensions) {
    if (typeof extension !== 'string') {
      throw new TypeError(`${optionPath} values must be strings`)
    }

    let normalizedExtension = extension.trim().toLowerCase()
    if (!/^\.[A-Za-z0-9_-]+$/.test(normalizedExtension)) {
      throw new TypeError(`${optionPath} values must use ".ext" format. Received "${extension}".`)
    }

    if (seen.has(normalizedExtension)) continue
    seen.add(normalizedExtension)
    normalizedExtensions.push(normalizedExtension)

View on GitHub (pinned to 9696913134)

Solutions

  1. Omit the option entirely if you want defaults or no customization
  2. Ensure dynamic arrays have at least one entry before passing
  3. Guard with `extensions.length > 0` when building config from untrusted input

Example fix

// before
files: { transformExtensions: [] }
// after
files: { transformExtensions: ['.css', '.js'] }
Defensive patterns

Strategy: validation

Validate before calling

if (Array.isArray(ext) && ext.length === 0) throw new Error('transformExtensions needs >=1 entry')

Prevention

When it happens

Trigger: Passing `files: { transformExtensions: [] }`, or a dynamically-built array that ends up empty after filtering (e.g. splitting an empty env var).

Common situations: Config generated from user input or env where filtering removes all entries; intentionally trying to disable transforms with an empty array instead of omitting the option.

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/be9f393c265f3e0f. Report an issue: GitHub.