remix-run/remix · error · TypeError

files.transforms must be an object

Error message

files.transforms must be an object

What it means

When provided, `files.transforms` must be a plain object mapping transform names to transform definitions. This error fires when it is null, a non-object, or an array.

Source

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

      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')
  }

  let normalizedTransforms = new Map<
    string,
    AssetRequestTransform<string, AssetRequestTransformParamMode>
  >()

  for (let [name, transform] of Object.entries(transforms)) {
    if (!/^[A-Za-z0-9_-]+$/.test(name)) {
      throw new TypeError(
        `files.transforms keys must use "transform-name" format. Received "${name}".`,
      )
    }

    if (
      transform === null ||
      typeof transform !== 'object' ||
      typeof transform.transform !== 'function'

View on GitHub (pinned to 9696913134)

Solutions

  1. Use a named map: `transforms: { md: { transform: fn } }`
  2. Move array-style anonymous transforms to `files.globalTransforms`
  3. Omit `transforms` if you have none

Example fix

// before
files: { transforms: [{ transform: fn }] }
// after
files: { globalTransforms: [fn] }
Defensive patterns

Strategy: type-guard

Validate before calling

if (files.transforms !== undefined && (typeof files.transforms !== 'object' || files.transforms === null || Array.isArray(files.transforms))) {
  throw new Error('files.transforms must be an object map')
}

Type guard

function isTransformMap(v: unknown): v is Record<string, { transform: Function }> {
  return !!v && typeof v === 'object' && !Array.isArray(v)
}

Prevention

When it happens

Trigger: Passing `files: { transforms: null }`, an array of transform objects, or a function where the object map is expected.

Common situations: Confusing `transforms` (named map) with `globalTransforms` (array); spreading optional config that leaves `null`; JSON configs with `"transforms": []`.

Related errors


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