{"id":"2eac60b12f1e0632","repo":"webpack/webpack","slug":"check-is-only-allowed-in-idle-status","errorCode":null,"errorMessage":"check() is only allowed in idle status","messagePattern":"check\\(\\) is only allowed in idle status","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/hmr/HotModuleReplacement.runtime.js","lineNumber":379,"sourceCode":"\t */\n\tfunction waitForBlockingPromises(fn) {\n\t\tif (blockingPromises === 0) return fn();\n\t\treturn /** @type {Promise<ModuleId[]>} */ (\n\t\t\tnew Promise(function (resolve) {\n\t\t\t\tblockingPromisesWaiting.push(function () {\n\t\t\t\t\tresolve(fn());\n\t\t\t\t});\n\t\t\t})\n\t\t);\n\t}\n\n\t/**\n\t * @param {boolean | ApplyOptions=} applyOnUpdate apply the update right away\n\t * @returns {Promise<ModuleId[] | null>} updated module ids or null\n\t */\n\tfunction hotCheck(applyOnUpdate) {\n\t\tif (currentStatus !== \"idle\") {\n\t\t\tthrow new Error(\"check() is only allowed in idle status\");\n\t\t}\n\t\treturn setStatus(\"check\")\n\t\t\t.then($hmrDownloadManifest$)\n\t\t\t.then(function (update) {\n\t\t\t\tif (!update) {\n\t\t\t\t\treturn setStatus(applyInvalidatedModules() ? \"ready\" : \"idle\").then(\n\t\t\t\t\t\tfunction () {\n\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\treturn setStatus(\"prepare\").then(function () {\n\t\t\t\t\t/** @type {ModuleId[]} */\n\t\t\t\t\tvar updatedModules = [];\n\t\t\t\t\tcurrentUpdateApplyHandlers = [];\n\n\t\t\t\t\treturn Promise.all(","sourceCodeStart":361,"sourceCodeEnd":397,"githubUrl":"https://github.com/webpack/webpack/blob/318421ea8ac81371f5171236a6efb63675576528/lib/hmr/HotModuleReplacement.runtime.js#L361-L397","documentation":"Runtime HMR state machine guard. module.hot.check() (the public API, also import.meta.webpackHot.check()) may only run from the 'idle' status; calling it while the runtime is already in 'check', 'prepare', 'ready', 'dispose', 'apply', or 'abort' would corrupt the update pipeline. The guard throws synchronously to enforce the documented state transition (idle -> check -> prepare -> ready/idle).","triggerScenarios":"Calling module.hot.check() twice in quick succession; calling check() from within a hotApply callback or an accept handler that already triggered an update; polling loops that call check() on a timer without waiting for the returned promise.","commonSituations":"Custom HMR UI that re-checks on a button click while a previous check is in flight; polling auto-update code that does not await the check() promise; event handlers that race with the HMR status.","solutions":["Always await the check() promise and verify module.hot.status() === 'idle' before calling check() again.","Gate manual checks: if (module.hot.status() === 'idle') module.hot.check();.","Serialize updates with a queue or flag so a second check cannot start before the first settles."],"exampleFix":"// before\nsetInterval(() => module.hot.check(), 1000);\n// after\nasync function poll() {\n  if (module.hot && module.hot.status() === 'idle') {\n    await module.hot.check();\n  }\n}","handlingStrategy":"validation","validationCode":"async function safeCheck() {\n  if (!module.hot || module.hot.status() !== 'idle') return null;\n  return module.hot.check();\n}","typeGuard":null,"tryCatchPattern":"try {\n  await module.hot.check();\n} catch (e) {\n  if (/only allowed in idle status/.test(e.message)) {\n    // status changed concurrently; skip this round\n  } else throw e;\n}","preventionTips":["Always check module.hot.status() === 'idle' before calling check().","Await the check() promise before initiating another check.","Avoid timer-based polling without a status guard."],"tags":["runtime","hmr","state-machine","dev-server"],"analyzedSha":"318421ea8ac81371f5171236a6efb63675576528","analyzedAt":"2026-08-03T19:39:56.731Z","schemaVersion":2}