remix-run/remix · error · TypeError
files.extensions values must use ".ext" format. Received "${
Error message
files.extensions values must use ".ext" format. Received "${extension}". What it means
After normalization (trim + lowercase), every `files.extensions` entry must match `.ext` — a leading dot followed only by letters, digits, underscores, or hyphens, with no additional dots or slashes. This error fires for malformed entries like `css`, `.tar.gz`, or `./css`.
Source
Thrown at packages/assets/src/lib/files/config.ts:197
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)
}
let transforms = files.transforms ?? {}
if (transforms === null || typeof transforms !== 'object' || Array.isArray(transforms)) {
throw new TypeError('files.transforms must be an object')View on GitHub (pinned to 9696913134)
Solutions
- Format each entry as a single dotted extension: `['.css', '.md', '.tar']` (use only the final segment for multi-part extensions)
- Add the leading dot programmatically if needed: `ext.startsWith('.') ? ext : '.' + ext`
- Double the leading dot issue in env-var-derived lists
Example fix
// before
files: { extensions: ['css', 'md'] }
// after
files: { extensions: ['.css', '.md'] } Defensive patterns
Strategy: validation
Validate before calling
let extensions = raw.map((e: string) => (e.startsWith('.') ? e : '.' + e)).filter((e: string) => /^\.[A-Za-z0-9_-]+$/.test(e)) Type guard
function isDotExt(e: string): boolean {
return /^\.[A-Za-z0-9_-]+$/.test(e.trim().toLowerCase())
} Prevention
- Get in the habit of the leading dot in extension lists
- Validate extensions against the regex when lists are user-supplied
When it happens
Trigger: Passing `extensions: ['css']` (missing dot), `.tar.gz` (two segments), `.d.ts`, or entries containing path separators or whitespace that leaves invalid characters.
Common situations: Developers omitting the leading dot out of habit from other tools' extension lists; multi-part extensions; extensions with special characters like `!` or `+` which the regex rejects.
Related errors
- files.extensions must be an array
- files.extensions values must be strings
- files.extensions cannot include compiled asset extensions li
- files.transforms must be an object
- files.transforms keys must use "transform-name" format. Rece
AI-assisted analysis of remix-run/remix@9696913134 (2026-08-27).
Data as JSON: /api/errors/2701749d7c526b4b.
Report an issue: GitHub.