{"record":{"id":"850222f75e575de3","repo":"remix-run/remix","slug":"message-850222","errorCode":null,"errorMessage":"${message}","messagePattern":"\\$\\{message\\}","errorType":"console","errorClass":null,"httpStatus":null,"severity":"info","filePath":"packages/node-hmr/src/lib/runtime.ts","lineNumber":148,"sourceCode":"          )\n        },\n        deps: normalizedDeps,\n      })\n      return\n    }\n\n    this.#acceptCallbacks.push(deps ?? (() => {}))\n  }\n\n  dispose(callback: DisposeCallback) {\n    this.#disposeCallbacks.push(callback)\n  }\n\n  invalidate(message?: string) {\n    this.#invalidated = true\n    this.#invalidationMessage = message\n    if (this.#isUpdating) {\n      if (message !== undefined) console.warn(message)\n      return\n    }\n    requestRestart(message)\n  }\n\n  on(_event: string, _callback: (data: unknown) => void | Promise<void>) {\n    void _event\n    void _callback\n  }\n\n  async disposeAll() {\n    for (let callback of this.#disposeCallbacks) {\n      await callback(this.data)\n    }\n  }\n\n  async update(timestamp: number, acceptedUrl: string): Promise<HotUpdateResult> {\n    this.#invalidated = false","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/remix-run/remix/blob/9696913134be3a4423513d2775f7b31d6917c049/packages/node-hmr/src/lib/runtime.ts#L130-L166","documentation":"The node HMR runtime's invalidate() logs the provided message via console.warn when the module is already in the middle of an update (isUpdating). The invalidation is recorded and applied after the current update completes rather than immediately requesting a restart.","triggerScenarios":"Calling import.meta.hot.invalidate(message) on a module runtime that is currently applying an update (e.g. from within an update-accepting callback that triggers another invalidation).","commonSituations":"Nested or cascading invalidations during HMR in Remix node apps; invalidate called inside a dispose or accept handler while an update is in flight.","solutions":["No action needed if the message is your own invalidation reason","Move invalidate() calls out of in-flight update callbacks if the warning is noisy","Debounce or conditionally invalidate to avoid repeated cascades"],"exampleFix":"// before\nimport.meta.hot.dispose(() => import.meta.hot.invalidate('from dispose'))\n// after\nimport.meta.hot.dispose(() => cleanup())\nif (needsRestart) import.meta.hot.invalidate('config changed')","handlingStrategy":"validation","validationCode":"if (!import.meta.hot.isUpdating) import.meta.hot.invalidate('reason')","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Avoid calling invalidate from inside dispose/accept callbacks while updates are in flight","Log invalidation reasons deliberately — they are echoed as warnings"],"tags":["hmr","invalidate","warning"],"backgroundTag":"hot-module-reload-invalidate","analyzedSha":"9696913134be3a4423513d2775f7b31d6917c049","analyzedAt":"2026-08-27T19:55:01.024Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}