remix-run/remix · error · TypeError

files.extensions values must be strings

Error message

files.extensions values must be strings

What it means

Each entry in `files.extensions` must be a string so it can be normalized (trimmed, lowercased) and validated as an extension. This error fires when an array entry is a number, boolean, null, or object.

Source

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

    return {
      extensions: [],
      globalTransforms: [],
      hasTransforms: false,
      maxRequestTransforms: defaultMaxRequestTransforms,
      transforms: new Map(),
    }
  }

  if (!Array.isArray(files.extensions)) {
    throw new TypeError('files.extensions must be an array')
  }

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

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

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

    if (reservedFileExtensions.has(normalizedExtension)) {
      throw new TypeError(
        `files.extensions cannot include compiled asset extensions like "${normalizedExtension}".`,
      )
    }

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

View on GitHub (pinned to 9696913134)

Solutions

  1. Map entries to strings: `extensions: rawExtensions.map(String)` or filter invalid entries
  2. Fix the source config so every extension is a quoted string
  3. Validate the list before passing it (see validation code)

Example fix

// before
files: { extensions: ['.css', env.MD_EXT_VERSION] }
// after
files: { extensions: ['.css', String(env.MD_EXT_VERSION)] }
Defensive patterns

Strategy: validation

Validate before calling

if (!files.extensions.every((e) => typeof e === 'string')) {
  files.extensions = files.extensions.map(String)
}

Type guard

function isStringArray(v: unknown[]): v is string[] {
  return v.every((e) => typeof e === 'string')
}

Prevention

When it happens

Trigger: `files: { extensions: ['.css', 42] }` or any array containing a non-string element.

Common situations: Env-var-derived lists parsed without mapping to strings (`.split()` returns strings, but JSON.parse of mixed arrays may not); YAML booleans/numbers sneaking into extension lists; typos like `extensions: ['.css', null]` from optional fields.

Related errors


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