openclaw - 💡(How to fix) Fix [Bug]: Gateway event loop hangs for over a hundred seconds during startup due to synchronous jiti plugin runtime resolution [1 comments, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#52807Fetched 2026-04-08 01:19:04
View on GitHub
Comments
1
Participants
1
Timeline
2
Reactions
0
Participants
Timeline (top)
commented ×1subscribed ×1

Gateway event loop hangs for over a hundred seconds during startup or on first request, caused by the plugin loader falling back to jiti's synchronous TypeScript module resolution.

Root Cause

Gateway event loop hangs for over a hundred seconds during startup or on first request, caused by the plugin loader falling back to jiti's synchronous TypeScript module resolution.

Code Example

ProxyGetProperty -> resolveRuntime -> resolveCreatePluginRuntime -> getJiti() -> jiti recursive module loading (22,391+ samples)

---

18:05:33 [ws] ⇄ res ✓ sessions.list 40ms
18:09:07 [ws] ⇄ res ✓ models.list 213270ms
18:09:07 [ws] ⇄ res ✓ chat.history 213380ms

---

[loader-diag] loadOpenClawPlugins called: hasFactory=false cache=false
  at resolvePluginProviders (src/plugins/providers.ts)
  at resolvePluginDiscoveryProviders
  at resolvePluginImplicitProviders
  at resolveImplicitProviders
  at resolveProvidersForModelsJson
  at planOpenClawModelsJson
  at ensureOpenClawModelsJson
RAW_BUFFERClick to expand / collapse

Bug type

Behavior bug (incorrect output/state without crash)

Summary

Gateway event loop hangs for over a hundred seconds during startup or on first request, caused by the plugin loader falling back to jiti's synchronous TypeScript module resolution.

Steps to reproduce

  1. Start the gateway: pnpm openclaw gateway --port 18789 --verbose
  2. Observe the gateway hangs during startup (or on first request that triggers models.list from the control UI)
  3. All WS requests queue up, Slack socket mode disconnects

Expected behavior

Gateway startup and first request should complete without noticeable delay.

Actual behavior

The event loop is blocked for over a hundred seconds. During this time:

  • All WS requests queue up (chat.history and models.list show 200,000+ ms response times)
  • Slack socket mode disconnects due to ping/pong timeout
  • The control UI appears frozen

The root cause chain:

  1. models.list -> loadModelCatalog -> ensureOpenClawModelsJson -> resolvePluginProviders
  2. resolvePluginProviders calls loadOpenClawPlugins({ cache: false, activate: false }) without createPluginRuntimeFactory
  3. Inside the loader, the Proxy get trap triggers resolveCreatePluginRuntime() which falls through to jiti
  4. jiti synchronously resolves the entire plugin runtime module tree (~30+ recursive levels), blocking the event loop

The gateway's initial loadGatewayPlugins call passes createPluginRuntimeFactory: createPluginRuntime correctly, but the module-level cache (_cachedCreatePluginRuntimeFactory) was only written when resolveCreatePluginRuntime() was actually invoked -- not eagerly when the factory was provided. If no plugin accessed runtime.* during the first load, the cache stayed empty.

OpenClaw version

2026.3.14

Operating system

macOS 15 (Apple Silicon)

Install method

pnpm dev

Model

anthropic/claude-opus-4-6

Provider / routing chain

openclaw -> anthropic

Logs, screenshots, and evidence

activity-monitor sample output shows 100% of samples in a single synchronous call stack:

ProxyGetProperty -> resolveRuntime -> resolveCreatePluginRuntime -> getJiti() -> jiti recursive module loading (22,391+ samples)

Gateway log showing the stall:

18:05:33 [ws] ⇄ res ✓ sessions.list 40ms
18:09:07 [ws] ⇄ res ✓ models.list 213270ms
18:09:07 [ws] ⇄ res ✓ chat.history 213380ms

Diagnostic logging confirmed the trigger:

[loader-diag] loadOpenClawPlugins called: hasFactory=false cache=false
  at resolvePluginProviders (src/plugins/providers.ts)
  at resolvePluginDiscoveryProviders
  at resolvePluginImplicitProviders
  at resolveImplicitProviders
  at resolveProvidersForModelsJson
  at planOpenClawModelsJson
  at ensureOpenClawModelsJson

Impact and severity

Affected: All gateway users (macOS confirmed, likely all platforms) Severity: High (gateway completely unresponsive for over a hundred seconds) Frequency: 100% on every startup Consequence: Slack disconnects, all WS clients time out, control UI appears broken. Users may kill and restart the gateway thinking it crashed.

Additional information

Fix is in src/plugins/loader.ts: eagerly seed _cachedCreatePluginRuntimeFactory when loadOpenClawPlugins receives createPluginRuntimeFactory in options (not deferred until resolveCreatePluginRuntime() is called), and also write back to the module-level cache after jiti fallback resolution. This ensures the jiti path is never hit during normal gateway operation.

Related files: src/plugins/loader.ts, src/gateway/server-plugins.ts, src/gateway/server.impl.ts, src/plugins/providers.ts

extent analysis

Fix Plan

To resolve the issue, we need to modify the loadOpenClawPlugins function in src/plugins/loader.ts to eagerly seed the _cachedCreatePluginRuntimeFactory when createPluginRuntimeFactory is provided in the options. We also need to write back to the module-level cache after jiti fallback resolution.

Step-by-Step Solution:

  1. Modify loadOpenClawPlugins function:
    export function loadOpenClawPlugins(options: {
      cache?: boolean;
      activate?: boolean;
      createPluginRuntimeFactory?: CreatePluginRuntimeFactory;
    } = {}): Promise<PluginProvider[]> {
      // ...
      if (options.createPluginRuntimeFactory) {
        // Eagerly seed the cache
        _cachedCreatePluginRuntimeFactory = options.createPluginRuntimeFactory;
      }
      // ...
    }
  2. Write back to the module-level cache after jiti fallback resolution:
    function resolveCreatePluginRuntime(): CreatePluginRuntimeFactory {
      // ...
      const factory = getJiti().resolveCreatePluginRuntime();
      // Write back to the module-level cache
      _cachedCreatePluginRuntimeFactory = factory;
      return factory;
    }
  3. Verify the cache is used:
    function resolveCreatePluginRuntime(): CreatePluginRuntimeFactory {
      if (_cachedCreatePluginRuntimeFactory) {
        return _cachedCreatePluginRuntimeFactory;
      }
      // ...
    }

Verification

To verify the fix, restart the gateway and observe the startup time and response times for models.list and chat.history requests. The gateway should start up without noticeable delay, and the response times should be significantly reduced.

Extra Tips

  • Make sure to test the fix on different platforms to ensure it resolves the issue across all affected environments.
  • Consider adding additional logging or monitoring to detect similar issues in the future.
  • Review the code changes to ensure they do not introduce any new bugs or performance issues.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

Gateway startup and first request should complete without noticeable delay.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING