{"record":{"id":"682c516472eae44d","repo":"remix-run/remix","slug":"hmr-must-create-an-object","errorCode":null,"errorMessage":"hmr must create an object","messagePattern":"hmr must create an object","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/assets/src/lib/asset-server.ts","lineNumber":1121,"sourceCode":"  }\n\n  return Promise.resolve(channelOrPromise).then((channel) => {\n    if (channel === undefined) return null\n    validateBrowserHmrChannel(channel)\n\n    if (isClosed()) {\n      channel.close()\n      return null\n    }\n\n    setUnsubscribe(channel.onFileEvents(handleFileEvents))\n    return channel\n  })\n}\n\nfunction validateBrowserHmrChannel(channel: unknown): asserts channel is BrowserHmrChannel {\n  if (channel === null || typeof channel !== 'object') {\n    throw new TypeError('hmr must create an object')\n  }\n  if (!('url' in channel) || typeof channel.url !== 'string') {\n    throw new TypeError('hmr must create a channel with a string url')\n  }\n  if (!('close' in channel) || typeof channel.close !== 'function') {\n    throw new TypeError('hmr must create a channel with a close function')\n  }\n  if (!('onFileEvents' in channel) || typeof channel.onFileEvents !== 'function') {\n    throw new TypeError('hmr must create a channel with an onFileEvents function')\n  }\n  if (!('updateWatchedFiles' in channel) || typeof channel.updateWatchedFiles !== 'function') {\n    throw new TypeError('hmr must create a channel with an updateWatchedFiles function')\n  }\n}\n\nfunction normalizeBasePath(basePath: string): string {\n  if (typeof basePath !== 'string') {\n    throw new TypeError('basePath must be a string')","sourceCodeStart":1103,"sourceCodeEnd":1139,"githubUrl":"https://github.com/remix-run/remix/blob/9696913134be3a4423513d2775f7b31d6917c049/packages/assets/src/lib/asset-server.ts#L1103-L1139","documentation":"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.","triggerScenarios":"Passing `--pool node` or `--pool vmThreads` to `remix test` when the value isn't in the supported `pools` array for the installed version.","commonSituations":"Habits from Vitest/Jest where pool names differ; renamed pools across CLI versions; typos.","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"],"exampleFix":"# before\nremix test --pool node\n# after\nremix test --pool threads","handlingStrategy":"type-guard","validationCode":"const SUPPORTED_POOLS = ['threads','forks'] as const;\nlet pool = process.env.TEST_POOL;\nif (pool && !(SUPPORTED_POOLS as readonly string[]).includes(pool)) {\n  console.error(`Pool must be one of: ${SUPPORTED_POOLS.join(', ')}`);\n  process.exit(1);\n}","typeGuard":"function isSupportedPool(v: string, pools: readonly string[]): v is string {\n  return pools.includes(v);\n}","tryCatchPattern":null,"preventionTips":["Copy pool names from the error message or docs","Omit --pool to use the default","Re-check pool names after CLI upgrades"],"tags":["cli","test","option-validation"],"backgroundTag":"unsupported-option-value","analyzedSha":"9696913134be3a4423513d2775f7b31d6917c049","analyzedAt":"2026-08-27T19:55:01.024Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}