{"record":{"id":"e1e12cbfc3845743","repo":"remix-run/remix","slug":"files-transforms-name-must-define-a-transform","errorCode":null,"errorMessage":"files.transforms.${name} must define a transform() function","messagePattern":"files\\.transforms\\.(.+?) must define a transform\\(\\) function","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/assets/src/lib/files/config.ts","lineNumber":235,"sourceCode":"\n  let normalizedTransforms = new Map<\n    string,\n    AssetRequestTransform<string, AssetRequestTransformParamMode>\n  >()\n\n  for (let [name, transform] of Object.entries(transforms)) {\n    if (!/^[A-Za-z0-9_-]+$/.test(name)) {\n      throw new TypeError(\n        `files.transforms keys must use \"transform-name\" format. Received \"${name}\".`,\n      )\n    }\n\n    if (\n      transform === null ||\n      typeof transform !== 'object' ||\n      typeof transform.transform !== 'function'\n    ) {\n      throw new TypeError(`files.transforms.${name} must define a transform() function`)\n    }\n\n    if (\n      'param' in transform &&\n      transform.param !== undefined &&\n      transform.param !== true &&\n      transform.param !== 'optional'\n    ) {\n      throw new TypeError(`files.transforms.${name}.param must be true or \"optional\"`)\n    }\n\n    normalizedTransforms.set(name, {\n      ...transform,\n      extensions: normalizeTransformExtensions(\n        transform.extensions,\n        `files.transforms.${name}.extensions`,\n      ),\n    })","sourceCodeStart":217,"sourceCodeEnd":253,"githubUrl":"https://github.com/remix-run/remix/blob/9696913134be3a4423513d2775f7b31d6917c049/packages/assets/src/lib/files/config.ts#L217-L253","documentation":"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.","triggerScenarios":"`transforms: { md: {} }`, `transforms: { md: null }`, or `transforms: { md: { extensions: [...] } }` where the transform function was forgotten or misnamed (e.g. `transformFn`).","commonSituations":"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.","solutions":["Ensure each entry defines `transform: (input) => ...`, e.g. `transforms: { md: { transform: mdTransform } }`","If the package exports a bare function, wrap it: `{ transform: importedFn }`"],"exampleFix":"// before\nfiles: { transforms: { md: { extensions: ['.md'], transformFn: fn } } }\n// after\nfiles: { transforms: { md: { extensions: ['.md'], transform: fn } } }","handlingStrategy":"type-guard","validationCode":"for (let [name, t] of Object.entries(files.transforms ?? {})) {\n  if (!t || typeof t !== 'object' || typeof t.transform !== 'function') {\n    throw new Error(`transform \"${name}\" is missing transform()`)\n  }\n}","typeGuard":"function isTransformDef(t: unknown): t is { transform: (...args: unknown[]) => unknown } {\n  return !!t && typeof t === 'object' && typeof (t as any).transform === 'function'\n}","tryCatchPattern":null,"preventionTips":["When importing transforms from packages, check whether the export is a bare function and wrap it as { transform: fn }","Write one shared validator for your config and run it on startup"],"tags":["config","files","transforms","validation"],"backgroundTag":"config-type-validation","analyzedSha":"9696913134be3a4423513d2775f7b31d6917c049","analyzedAt":"2026-08-27T19:55:01.024Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}