{"record":{"id":"e8e30ed1f876597f","repo":"remix-run/remix","slug":"files-transforms-keys-must-use-transform-name-fo","errorCode":null,"errorMessage":"files.transforms keys must use \"transform-name\" format. Received \"${name}\".","messagePattern":"files\\.transforms keys must use \"transform-name\" format\\. Received \"(.+?)\"\\.","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/assets/src/lib/files/config.ts","lineNumber":225,"sourceCode":"\n    if (seen.has(normalizedExtension)) continue\n    seen.add(normalizedExtension)\n    normalizedExtensions.push(normalizedExtension)\n  }\n\n  let transforms = files.transforms ?? {}\n  if (transforms === null || typeof transforms !== 'object' || Array.isArray(transforms)) {\n    throw new TypeError('files.transforms must be an object')\n  }\n\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    ) {","sourceCodeStart":207,"sourceCodeEnd":243,"githubUrl":"https://github.com/remix-run/remix/blob/9696913134be3a4423513d2775f7b31d6917c049/packages/assets/src/lib/files/config.ts#L207-L243","documentation":"Keys in the `files.transforms` map become URL segments (e.g. `/transform-name/file.ext`), so each name must match `[A-Za-z0-9_-]+` — no dots, slashes, spaces, or unicode. This error fires for keys like `md.min`, `my transform`, or `md/v2`.","triggerScenarios":"Naming a transform with characters that cannot appear in a URL path segment, such as dots, spaces, slashes, or punctuation.","commonSituations":"Naming transforms after file extensions (`'.md'` as a key); names copied from display labels with spaces; versioned names like `md@2`.","solutions":["Rename keys to use only letters, digits, `_`, and `-`, e.g. `md`, `minify-md`","Strip invalid characters before building config if names come from user input: `name.replace(/[^A-Za-z0-9_-]/g, '')`"],"exampleFix":"// before\nfiles: { transforms: { 'md.min': { transform: fn } } }\n// after\nfiles: { transforms: { 'md-min': { transform: fn } } }","handlingStrategy":"validation","validationCode":"if (!/^[A-Za-z0-9_-]+$/.test(name)) {\n  throw new Error(`transform name \"${name}\" must use [A-Za-z0-9_-] only`)\n}","typeGuard":"function isValidTransformName(name: string): boolean {\n  return /^[A-Za-z0-9_-]+$/.test(name)\n}","tryCatchPattern":null,"preventionTips":["Name transforms like URL slugs: lowercase, hyphens, no dots","Sanitize user-provided transform names before config assembly"],"tags":["config","files","transforms","naming"],"backgroundTag":"config-format-validation","analyzedSha":"9696913134be3a4423513d2775f7b31d6917c049","analyzedAt":"2026-08-27T19:55:01.024Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}