vercel/next.js · error
Invalid "cacheHandlers" provided, expected an object e.g. {
Error message
Invalid "cacheHandlers" provided, expected an object e.g. { default: '/my-handler.js' }, received ${JSON.stringify(result.cacheHandlers)} What it means
Thrown at config.ts:1443 when `cacheHandlers` is provided but `typeof result.cacheHandlers !== 'object'`. `cacheHandlers` maps cache-handler names to module paths (e.g. `{ default: '/my-handler.js' }`). Arrays are objects in JS and would pass this check but be caught by downstream key validation; non-object primitives (string, number, boolean) fail here.
Source
Thrown at packages/next/src/server/config.ts:1444
const staticStaleTime = result.experimental.staleTimes?.static
defaultCacheLifeProfile.stale =
staticStaleTime ?? defaultConfig.experimental?.staleTimes?.static
}
if (defaultCacheLifeProfile.revalidate === undefined) {
defaultCacheLifeProfile.revalidate = defaultDefault.revalidate
}
if (defaultCacheLifeProfile.expire === undefined) {
defaultCacheLifeProfile.expire =
result.expireTime ?? defaultDefault.expire
}
}
}
if (result.cacheHandlers) {
const allowedHandlerNameRegex = /^[a-z-]+$/
if (typeof result.cacheHandlers !== 'object') {
throw new Error(
`Invalid "cacheHandlers" provided, expected an object e.g. { default: '/my-handler.js' }, received ${JSON.stringify(result.cacheHandlers)}`
)
}
const handlerKeys = Object.keys(result.cacheHandlers)
const invalidHandlerItems: Array<{ key: string; reason: string }> = []
for (const key of handlerKeys) {
if (key === 'private') {
invalidHandlerItems.push({
key,
reason:
'The cache handler for "use cache: private" cannot be customized.',
})
} else if (!allowedHandlerNameRegex.test(key)) {
invalidHandlerItems.push({
key,
reason: 'key must only use characters a-z and -',View on GitHub (pinned to 0ae8c72462)
Solutions
- Provide `cacheHandlers` as an object mapping handler names to resolved file paths.
- Remove the `cacheHandlers` key if you are not customizing cache handlers.
Example fix
// before
module.exports = { cacheHandlers: '/my-handler.js' }
// after
module.exports = { cacheHandlers: { default: '/my-handler.js' } } Defensive patterns
Strategy: type-guard
Validate before calling
if (cacheHandlers !== undefined && (typeof cacheHandlers !== 'object' || Array.isArray(cacheHandlers))) {
throw new Error('cacheHandlers must be a plain object');
} Type guard
function isHandlerMap(x: unknown): x is Record<string, string> {
return typeof x === 'object' && x !== null && !Array.isArray(x);
} Prevention
- Provide `cacheHandlers` as a `{ name: path }` object map.
- Omit the key when not customizing handlers.
When it happens
Trigger: `cacheHandlers: '/my-handler.js'` (string); `cacheHandlers: ['default']` (array — passes here but fails key validation); `cacheHandlers: 42`.
Common situations: Misreading the option as a path string; migrating from an older array-based custom-handler config.
Related errors
- Specified i18n.locales should be an Array received ${typeof
- Specified i18n.defaultLocale should be a string. See more in
- Specified i18n.domains must be an array of domain objects e.
- Specified i18n.locales must be an array of locale strings e.
- Specified i18n.localeDetection should be undefined or a bool
AI-assisted analysis of vercel/next.js@0ae8c72462 (2026-08-06).
Data as JSON: /api/errors/899b631ccdbcacff.
Report an issue: GitHub.