{"record":{"id":"38a2587f78c653f6","repo":"remix-run/remix","slug":"browser-hmr-is-disabled-for-this-node-hmr-runtime","errorCode":null,"errorMessage":"Browser HMR is disabled for this node-hmr runtime","messagePattern":"Browser HMR is disabled for this node-hmr runtime","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/node-hmr/src/lib/runtime.ts","lineNumber":290,"sourceCode":"    }\n  >()\n\n  process.on('message', (message: unknown) => {\n    if (!isBrowserHmrChannelMessage(message)) return\n\n    let request = pendingBrowserHmrChannelRequests.get(message.requestId)\n    if (request === undefined) return\n\n    clearTimeout(request.timer)\n    pendingBrowserHmrChannelRequests.delete(message.requestId)\n    request.resolve(message.url)\n  })\n\n  let runtime: RemixNodeHmrRuntime = {\n    async createBrowserHmrChannel() {\n      browserEventUrl ??= await requestBrowserHmrChannelUrl()\n      if (browserEventUrl === undefined) {\n        throw new Error('Browser HMR is disabled for this node-hmr runtime')\n      }\n\n      let id = browserHmrChannelId++\n      let watchedFiles = new Set<string>()\n      let handlers = new Set<BrowserHmrFileEventHandler>()\n      let closed = false\n      browserHmrChannels.set(id, {\n        async handleFileEvents(events) {\n          let eventGroups = await Promise.all([...handlers].map((handler) => handler(events)))\n          return eventGroups.flat()\n        },\n      })\n\n      function updateWatchedFiles(delta: BrowserHmrWatchedFileDelta): void {\n        if (closed) return\n\n        for (let file of delta.add) {\n          watchedFiles.add(file)","sourceCodeStart":272,"sourceCodeEnd":308,"githubUrl":"https://github.com/remix-run/remix/blob/9696913134be3a4423513d2775f7b31d6917c049/packages/node-hmr/src/lib/runtime.ts#L272-L308","documentation":"createBrowserHmrChannel() in the node-hmr runtime asks the parent node-hmr process for a browser event URL; if none is returned (the runtime is not running under node-hmr's supervision or browser HMR is disabled), the URL stays undefined and the method throws. It signals that browser asset tooling cannot connect because no browser HMR event stream exists for this child process.","triggerScenarios":"Calling remixNodeHmrRuntime.createBrowserHmrChannel() from a process started outside the node-hmr supervisor, or when the parent node-hmr run has browser HMR disabled, so requestBrowserHmrChannelUrl() resolves to undefined.","commonSituations":"Dev servers started with plain node/npm run instead of the node-hmr CLI; browser HMR disabled via config in the parent; plugins invoking browser channel APIs in standalone scripts or tests.","solutions":["Start the dev process through node-hmr so a browser HMR event stream exists","Enable browser HMR in the parent node-hmr configuration","Feature-detect before use: only call createBrowserHmrChannel when the runtime advertises browser HMR (e.g. guard on runtime availability checks)"],"exampleFix":"// before\nlet channel = await runtime.createBrowserHmrChannel()\n\n// after\nlet channel\ntry {\n  channel = await runtime.createBrowserHmrChannel()\n} catch {\n  // running outside node-hmr; skip browser asset wiring\n  channel = null\n}","handlingStrategy":"try-catch","validationCode":"// detect node-hmr supervision before wiring browser channel\nlet underNodeHmr = Boolean(globalThis.__nodeHmrRuntime) // runtime global installed by node-hmr\nif (underNodeHmr) {\n  let channel = await runtime.createBrowserHmrChannel()\n}","typeGuard":"function isUnderNodeHmr(): boolean {\n  return typeof globalThis !== 'undefined' && '__nodeHmrRuntime' in globalThis\n}","tryCatchPattern":"try {\n  channel = await runtime.createBrowserHmrChannel()\n} catch (error) {\n  if (error instanceof Error && error.message === 'Browser HMR is disabled for this node-hmr runtime') {\n    channel = null // degrade gracefully\n  } else throw error\n}","preventionTips":["Start dev servers via the node-hmr CLI","Guard browser-HMR wiring behind a runtime availability check","Enable browser HMR in the parent node-hmr config when needed"],"tags":["node-hmr","hmr","dev-server","runtime-unavailable"],"backgroundTag":"hmr-runtime-unavailable","analyzedSha":"9696913134be3a4423513d2775f7b31d6917c049","analyzedAt":"2026-08-27T19:55:01.024Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}