Description
When running OpenClaw from source (not the npm global package), the gateway can enter an infinite CPU loop (100%+ CPU, completely frozen, no output). This is caused by a circular require through jiti (the TypeScript-on-demand compiler).
Reproduction (Intermittent)
- Clone the repo and build from source
- Run the gateway via
node dist/index.js gateway run
- The bug is intermittent — it depends on the jiti disk cache state. Same code works fine on a "cold" cache but loops on certain "warm" cache states.
Root Cause
Infinite recursion loop captured via Node debugger:
normalizeAliases → createJiti → eval_module → jitiRequire →
loadChannelConfigSurfaceModuleSync → collectBundledChannelConfigs →
collectBundledPluginMetadataForPackageRoot → listBundledPluginMetadata →
buildChatChannelMetaById → jiti require → loop back to createJiti
When jiti loads a plugin's config file, it triggers a code path that re-enters plugin discovery, which tries to load another config file via jiti — creating infinite recursion.
Likely Fix Points
-
src/plugins/bundled-plugin-metadata.ts — collectBundledChannelConfigs loads a plugin's config surface via jiti during plugin discovery. If that config surface imports anything that re-enters listBundledPluginMetadata, you get the loop. Fix: defer loading config surfaces until after plugin discovery is complete, or cache plugin metadata before loading any config surfaces.
-
src/channels/chat-meta.ts — buildChatChannelMetaById() at module load time triggers the re-entry. Fix: defer to lazy initialization.
Workaround
Install OpenClaw from npm globally (npm install -g openclaw). The npm package is pre-built and doesn't use jiti, so the circular require is never hit.
Environment
- OpenClaw: 2026.3.24–2026.3.28 (from source)
- Node: v22.22.0
- OS: Ubuntu, kernel 6.8.0-106-generic
- Reproduces intermittently across multiple commits (cff6dc9, 2899ce5, a7a89fb)
Description
When running OpenClaw from source (not the npm global package), the gateway can enter an infinite CPU loop (100%+ CPU, completely frozen, no output). This is caused by a circular require through jiti (the TypeScript-on-demand compiler).
Reproduction (Intermittent)
node dist/index.js gateway runRoot Cause
Infinite recursion loop captured via Node debugger:
When jiti loads a plugin's config file, it triggers a code path that re-enters plugin discovery, which tries to load another config file via jiti — creating infinite recursion.
Likely Fix Points
src/plugins/bundled-plugin-metadata.ts—collectBundledChannelConfigsloads a plugin's config surface via jiti during plugin discovery. If that config surface imports anything that re-enterslistBundledPluginMetadata, you get the loop. Fix: defer loading config surfaces until after plugin discovery is complete, or cache plugin metadata before loading any config surfaces.src/channels/chat-meta.ts—buildChatChannelMetaById()at module load time triggers the re-entry. Fix: defer to lazy initialization.Workaround
Install OpenClaw from npm globally (
npm install -g openclaw). The npm package is pre-built and doesn't use jiti, so the circular require is never hit.Environment