remix-run/remix · error · TypeError
${message}
Error message
${message} What it means
While serializing request transform invocations, each entry is normalized by normalizeAssetTransformInvocation; if an entry is malformed (unknown transform name, bad argument shape, etc.) the nested validator's message is re-thrown as a TypeError from serializeAssetTransformInvocations.
Source
Thrown at packages/assets/src/lib/files/config.ts:360
seen.add(normalizedExtension)
normalizedExtensions.push(normalizedExtension)
}
return normalizedExtensions
}
export function serializeAssetTransformInvocations<transforms extends AssetRequestTransformMap>(
transforms: readonly AssetTransformInvocation<transforms>[],
transformsByName: ResolvedAssetRequestTransformMap,
maxTransforms = defaultMaxRequestTransforms,
): string[] {
if (transforms.length > maxTransforms) {
throw new TypeError(`Expected at most ${maxTransforms} request transforms`)
}
return transforms.map((transformInvocation) =>
normalizeAssetTransformInvocation(transformInvocation, transformsByName, (message) => {
throw new TypeError(message)
}),
)
}
export function parseAssetTransformInvocations(
transformsQuery: readonly string[],
transformsByName: ResolvedAssetRequestTransformMap,
maxTransforms = defaultMaxRequestTransforms,
): readonly (string | readonly [string, string])[] {
if (transformsQuery.length > maxTransforms) {
throw new TypeError(`Expected at most ${maxTransforms} request transforms`)
}
return transformsQuery.map((transformQuery) =>
parseSerializedAssetTransformInvocation(transformQuery, transformsByName, (message) => {
throw new TypeError(message)
}),
)View on GitHub (pinned to 9696913134)
Solutions
- Check the exact nested message for the offending field and fix that entry
- Verify every invocation name exists in the resolved transforms map before serializing
- Regenerate/clear cached transform URLs after changing the transform registry
Example fix
// before
getHrefTransform([{ name: 'minifyy', args: [] }], map)
// after
getHrefTransform([{ name: 'minify', args: [] }], map) Defensive patterns
Strategy: try-catch
Validate before calling
const valid = invocations.every((i) => i.name in transformsByName)
if (!valid) throw new Error('unknown transform name') Type guard
function isKnownTransform(name: string, map: ResolvedAssetRequestTransformMap): boolean {
return name in map
} Try / catch
try { serializeAssetTransformInvocations(list, map) } catch (e) { if (e instanceof TypeError) logBadInvocation(e.message); throw e } Prevention
- Derive invocation names from the registered map, never hardcode strings
- Type invocations against the map's keys
When it happens
Trigger: Passing an invocation whose name is not in transformsByName, or whose args don't match the transform's declared argument types, to getHrefTransform/serializeAssetTransformInvocations.
Common situations: Renaming or removing a registered transform while stale references (cached URLs, old client bundles) still request it; typos in transform names; passing raw strings instead of invocation objects.
Understand the failure class
Background: Invalid option value errors: "must be one of", "is not a valid", and "only allows" failures explained — this error's family across 23 libraries.
Related errors
- Expected at most ${maxTransforms} request transforms
- files.transforms must be an object
- files.transforms.${name} must define a transform() function
- files.transforms.${name}.param must be true or "optional"
- files.globalTransforms must be an array
AI-assisted analysis of remix-run/remix@9696913134 (2026-08-27).
Data as JSON: /api/errors/5e8ecb44190d1901.
Report an issue: GitHub.