remix-run/remix · error · TypeError
hmr must create an object
Error message
hmr must create an object
What it means
The `--pool` option selects the test execution pool and must be one of the supported `RemixTestPool` values (the exact list is included in the message). `parsePool` returns early for undefined or listed values and throws for anything else, so a typo'd or ported-from-Vitest pool name fails fast.
Source
Thrown at packages/assets/src/lib/asset-server.ts:1121
}
return Promise.resolve(channelOrPromise).then((channel) => {
if (channel === undefined) return null
validateBrowserHmrChannel(channel)
if (isClosed()) {
channel.close()
return null
}
setUnsubscribe(channel.onFileEvents(handleFileEvents))
return channel
})
}
function validateBrowserHmrChannel(channel: unknown): asserts channel is BrowserHmrChannel {
if (channel === null || typeof channel !== 'object') {
throw new TypeError('hmr must create an object')
}
if (!('url' in channel) || typeof channel.url !== 'string') {
throw new TypeError('hmr must create a channel with a string url')
}
if (!('close' in channel) || typeof channel.close !== 'function') {
throw new TypeError('hmr must create a channel with a close function')
}
if (!('onFileEvents' in channel) || typeof channel.onFileEvents !== 'function') {
throw new TypeError('hmr must create a channel with an onFileEvents function')
}
if (!('updateWatchedFiles' in channel) || typeof channel.updateWatchedFiles !== 'function') {
throw new TypeError('hmr must create a channel with an updateWatchedFiles function')
}
}
function normalizeBasePath(basePath: string): string {
if (typeof basePath !== 'string') {
throw new TypeError('basePath must be a string')View on GitHub (pinned to 9696913134)
Solutions
- Use one of the pools listed in the error message, e.g. `--pool threads` or `--pool forks`
- Omit `--pool` to use the default
- Re-check supported pools after upgrading the CLI
Example fix
# before remix test --pool node # after remix test --pool threads
Defensive patterns
Strategy: type-guard
Validate before calling
const SUPPORTED_POOLS = ['threads','forks'] as const;
let pool = process.env.TEST_POOL;
if (pool && !(SUPPORTED_POOLS as readonly string[]).includes(pool)) {
console.error(`Pool must be one of: ${SUPPORTED_POOLS.join(', ')}`);
process.exit(1);
} Type guard
function isSupportedPool(v: string, pools: readonly string[]): v is string {
return pools.includes(v);
} Prevention
- Copy pool names from the error message or docs
- Omit --pool to use the default
- Re-check pool names after CLI upgrades
When it happens
Trigger: Passing `--pool node` or `--pool vmThreads` to `remix test` when the value isn't in the supported `pools` array for the installed version.
Common situations: Habits from Vitest/Jest where pool names differ; renamed pools across CLI versions; typos.
Related errors
- mounts must include at least one entry
- hmr must be a function
- ${matcherName} requires a mock function with a .mock.calls p
- throw new AssertionError(options)
- throw new AssertionError({ message, actual, expected, operat
AI-assisted analysis of remix-run/remix@9696913134 (2026-08-27).
Data as JSON: /api/errors/682c516472eae44d.
Report an issue: GitHub.