remix-run/remix · error · TypeError

files.transforms.${name} must define a transform() function

Error message

files.transforms.${name} must define a transform() function

What it means

Every entry in `files.transforms` must be an object (or provide) a `transform` function — this is the code that rewrites the matched file's contents. The error fires when the entry is null, a non-object, or has no callable `transform` property.

Source

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

  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'
    ) {
      throw new TypeError(`files.transforms.${name} must define a transform() function`)
    }

    if (
      'param' in transform &&
      transform.param !== undefined &&
      transform.param !== true &&
      transform.param !== 'optional'
    ) {
      throw new TypeError(`files.transforms.${name}.param must be true or "optional"`)
    }

    normalizedTransforms.set(name, {
      ...transform,
      extensions: normalizeTransformExtensions(
        transform.extensions,
        `files.transforms.${name}.extensions`,
      ),
    })

View on GitHub (pinned to 9696913134)

Solutions

  1. Ensure each entry defines `transform: (input) => ...`, e.g. `transforms: { md: { transform: mdTransform } }`
  2. If the package exports a bare function, wrap it: `{ transform: importedFn }`

Example fix

// before
files: { transforms: { md: { extensions: ['.md'], transformFn: fn } } }
// after
files: { transforms: { md: { extensions: ['.md'], transform: fn } } }
Defensive patterns

Strategy: type-guard

Validate before calling

for (let [name, t] of Object.entries(files.transforms ?? {})) {
  if (!t || typeof t !== 'object' || typeof t.transform !== 'function') {
    throw new Error(`transform "${name}" is missing transform()`)
  }
}

Type guard

function isTransformDef(t: unknown): t is { transform: (...args: unknown[]) => unknown } {
  return !!t && typeof t === 'object' && typeof (t as any).transform === 'function'
}

Prevention

When it happens

Trigger: `transforms: { md: {} }`, `transforms: { md: null }`, or `transforms: { md: { extensions: [...] } }` where the transform function was forgotten or misnamed (e.g. `transformFn`).

Common situations: Importing a transform from a package that exports the function directly rather than a `{ transform }` wrapper; typos in the property name; partially copied config examples.

Related errors


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