remix-run/remix · error · TypeError
files.cache must implement the FileStorage interface
Error message
files.cache must implement the FileStorage interface
What it means
When `files.cache` is provided it must implement the FileStorage interface (objects with `get` and `set` functions). The library duck-types the option at normalization time rather than trusting the type system, because users often pass plain objects or partially-implemented caches.
Source
Thrown at packages/assets/src/lib/files/config.ts:302
transform.extensions,
`files.globalTransforms[${index}].extensions`,
),
})
}
let maxRequestTransforms = files.maxRequestTransforms ?? defaultMaxRequestTransforms
if (!Number.isInteger(maxRequestTransforms) || maxRequestTransforms < 1) {
throw new TypeError('files.maxRequestTransforms must be a positive integer')
}
if (files.cache !== undefined) {
if (
files.cache === null ||
typeof files.cache !== 'object' ||
typeof files.cache.get !== 'function' ||
typeof files.cache.set !== 'function'
) {
throw new TypeError('files.cache must implement the FileStorage interface')
}
}
return {
cache: files.cache,
extensions: normalizedExtensions,
globalTransforms: normalizedGlobalTransforms,
hasTransforms: normalizedTransforms.size > 0 || normalizedGlobalTransforms.length > 0,
maxRequestTransforms,
transforms: normalizedTransforms,
}
}
function normalizeTransformExtensions(
extensions: readonly string[] | undefined,
optionPath: string,
): readonly string[] | undefined {
if (extensions === undefined) return undefinedView on GitHub (pinned to 9696913134)
Solutions
- Implement both get and set methods on the cache object
- If wrapping an external cache, adapt its method names: `get: (k) => store.read(k), set: (k, v) => store.write(k, v)`
- Omit `cache` to use the default cache behavior
Example fix
// before
files: { cache: {} }
// after
files: {
cache: {
get(key) { return myStore[key] },
set(key, value) { myStore[key] = value },
},
} Defensive patterns
Strategy: type-guard
Validate before calling
const c = options.files?.cache
if (c && (typeof c.get !== 'function' || typeof c.set !== 'function')) throw new Error('cache must implement FileStorage') Type guard
function isFileStorage(c: unknown): c is FileStorage {
return c != null && typeof c === 'object'
&& typeof (c as FileStorage).get === 'function'
&& typeof (c as FileStorage).set === 'function'
} Prevention
- Implement FileStorage as a small class or object literal with get/set
- Add a unit test asserting your cache satisfies the interface
When it happens
Trigger: Passing `files: { cache: {} }`, a Map instance, a cache module namespace without get/set, or null to resolveAssetServerOptions/normalizeFilesOptions.
Common situations: Trying to use a custom in-memory LRU or a plain object literal as cache, wrapping an existing cache library whose methods are named differently (e.g. read/write), or passing a cache that was serialized/structured-cloned so methods were lost.
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
- files.maxRequestTransforms must be a positive integer
- ${optionPath} must be an array
- ${optionPath} must include at least one extension
- ${optionPath} values must be strings
- ${optionPath} values must use ".ext" format. Received "${ext
AI-assisted analysis of remix-run/remix@9696913134 (2026-08-27).
Data as JSON: /api/errors/79b631e421283232.
Report an issue: GitHub.