openclaw - ✅(Solved) Fix [Bug]: status command is slow because telegram doctor contract loading uses slow jiti path [2 pull requests, 1 comments, 2 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#68282Fetched 2026-04-18 05:53:20
View on GitHub
Comments
1
Participants
2
Timeline
6
Reactions
0
Author
Participants
Timeline (top)
cross-referenced ×2referenced ×2commented ×1subscribed ×1

openclaw status and related status commands are slow on a fresh process because config validation loads Telegram doctor contract artifacts through the default jiti path, which is much slower than native loading for built dist/extensions/* JS artifacts.

This does not appear to be a gateway/runtime failure. The gateway is healthy and responsive after restart, but each new openclaw status process pays a large first-call penalty during config validation.

Error Message

  • openclaw status
  • openclaw status --deep
  • openclaw status --json
  • openclaw status --usage

Root Cause

status looks broken or hung even though runtime is healthy. The delay is large enough to mislead operators into suspecting gateway or channel failures when the bottleneck is actually config validation + contract loading.

Fix Action

Fixed

PR fix notes

PR #68324: fix(plugins): enable native jiti for doctor-contract loader to cut status cold-start ~13s

Description (problem / solution / changelog)

Summary

Fixes #68282 — `openclaw status` (and `--json`, `--deep`, `--usage`) pays a ~15s first-call penalty on every fresh process, dominated by doctor-contract loading through the default jiti path. The reporter measured the contract-api artifact in isolation at 15.7s default vs 2.1s with `tryNative: true`, and `listPluginDoctorLegacyConfigRules` ate 21.8s of the total 17s config-validation wall time.

Root cause

`src/plugins/doctor-contract-registry.ts:46-52` built the loader via:

```ts function getJiti(modulePath: string) { return getCachedPluginJitiLoader({ cache: jitiLoaders, modulePath, importerUrl: import.meta.url, }); } ```

Without `tryNative` explicit, `getCachedPluginJitiLoader` defers to `resolvePluginLoaderJitiTryNative` in `src/plugins/sdk-alias.ts`. That function has an unconditional guard that returns `false` whenever `modulePath` matches `/dist/extensions/` — which is exactly where contract artifacts live in shipped builds (`dist/extensions/telegram/contract-api.js` etc.). So every doctor contract load took the slow transpile-and-cache path on cold start.

Fix

Pass `tryNative: process.platform !== "win32"` explicitly from the doctor registry:

```ts function getJiti(modulePath: string) { return getCachedPluginJitiLoader({ cache: jitiLoaders, modulePath, importerUrl: import.meta.url, tryNative: process.platform !== "win32", }); } ```

Jiti keeps its transpile path as a fallback on native-import failure, so aliased `openclaw/plugin-sdk/*` imports inside contract modules still resolve via the existing alias-map flow. Windows is left on the pre-existing slower path because `supportsNativeJitiRuntime` in `sdk-alias.ts` disables native jiti for that platform anyway.

Test plan

  • Added a regression test `enables native jiti loading on Linux for contract-api modules (#68282)` in `src/plugins/doctor-contract-registry.test.ts`, mirroring the existing `disables native jiti loading on Windows for contract-api modules` case. Asserts `createJiti` is invoked with `tryNative: true` when `process.platform` returns `linux`.
  • Existing Windows test (`disables native jiti loading on Windows`) still passes because the new pass-through evaluates to `false` on Windows.
  • `NODE_OPTIONS=--max-old-space-size=8192 npx tsc --noEmit` — 245 baseline on main, 245 on branch (no delta).
  • `pnpm exec oxlint` on both touched files — 0 warnings, 0 errors.

Local full vitest is blocked by pre-existing `test/non-isolated-runner.ts` drift (reproduces on `main`); CI exercises the new case normally.

Risk

  • Contract artifacts in `dist/extensions/<plugin>/` are built JS bundles — native import is the fast and correct path for them. The transpile fallback remains active if a native-load edge case (e.g. a contract module that imports a TS source path directly) fails.
  • Windows path is unchanged because `supportsNativeJitiRuntime` already disables native jiti there.
  • No API surface changes; doctor-rule loading emits the same `PluginDoctorContractEntry` values, just faster on first call.

Measurement (from issue body)

PathFirst-call
default jiti~15.7s
`tryNative: true`~2.1s
native `import()`~3.0s

This PR puts the doctor registry on the 2.1s path.

Changed files

  • src/plugins/doctor-contract-registry.test.ts (modified, +31/-0)
  • src/plugins/doctor-contract-registry.ts (modified, +12/-0)

PR #68348: fix: use native loading for doctor contract API to speed up status command

Description (problem / solution / changelog)

Summary

Fixes openclaw#68282

The openclaw status and related status commands are slow on a fresh process because doctor contract loading uses the slow jiti path instead of native loading for built artifacts.

Root Cause

The getJiti function in doctor-contract-registry.ts was not passing tryNative flag to getCachedPluginJitiLoader, causing built artifacts to be loaded through the slow jiti path instead of native loading.

Fix

  • Import shouldPreferNativeJiti from sdk-alias.js
  • Pass tryNative: shouldPreferNativeJiti(modulePath) to getCachedPluginJitiLoader

This matches the pattern used in other loader functions (e.g., loader.ts line 443, bundled-capability-runtime.ts line 206, runtime-plugin-boundary.ts line 118')

Test Plan

  • Relevant unit tests pass (src/plugins/doctor-contract-registry.test.ts - 4 tests passed)
  • Follows existing code style

Closes openclaw#68282

Changed files

  • src/plugins/doctor-contract-registry.ts (modified, +2/-0)
RAW_BUFFERClick to expand / collapse

Summary

openclaw status and related status commands are slow on a fresh process because config validation loads Telegram doctor contract artifacts through the default jiti path, which is much slower than native loading for built dist/extensions/* JS artifacts.

This does not appear to be a gateway/runtime failure. The gateway is healthy and responsive after restart, but each new openclaw status process pays a large first-call penalty during config validation.

Affected version

  • OpenClaw: 2026.4.15
  • Install method: global npm install
  • Node: v24.13.1
  • OS: Ubuntu Linux

Observed behavior

  • openclaw status
  • openclaw status --deep
  • openclaw status --json
  • openclaw status --usage

All hang or feel stalled for a long time on a fresh process even when:

  • gateway service is active
  • openclaw models status --check succeeds
  • runtime logs show healthy status, channels.status, and health responses

Reproduction notes

The slow path is reproducible by timing the config loader / validator directly from the installed package:

  1. readBestEffortConfig() takes about 17 to 18 seconds.
  2. The time is not spent in file I/O for openclaw.json.
  3. The main cost is config validation.
  4. The main cost inside config validation is legacy doctor rule loading.
  5. The dominant plugin is telegram.

Timing evidence

Config read and validation

  • readBestEffortConfig() elapsed: about 17519ms
  • validateConfigObjectWithPlugins(...): about 16955ms
  • validateConfigObject(...): about 16034ms

Legacy rule loading

  • findLegacyConfigIssues(...): about 22046ms
  • listPluginDoctorLegacyConfigRules({ pluginIds }): about 21804ms

Per-plugin timing for doctor legacy rule loading:

  • telegram: about 14386ms
  • discord: about 306ms
  • anthropic: about 752ms
  • most others: near zero

Loader comparison for the same Telegram contract artifact

Target artifact:

  • dist/extensions/telegram/contract-api.js

Fresh-process timings:

  • default jiti loader path: about 15703ms
  • jiti with tryNative: true: about 2122ms
  • native dynamic import(...): about 3045ms

Within the same process, cached repeated loads are fast, so this is specifically a cold-start / first-load issue that hurts CLI commands like status.

Likely root cause

In the installed build, doctor contract loading uses:

  • dist/io-*.js -> loadPluginDoctorContractEntry(...) -> getJiti(contractSource)(contractSource)

But the loader policy currently forces bundled dist/extensions/* modules away from native loading:

  • resolvePluginLoaderJitiTryNative(...) returns false for bundled dist extension paths

That means already-built JS artifacts such as:

  • dist/extensions/telegram/contract-api.js

still go through the slow jiti path during config validation.

Why this matters

status looks broken or hung even though runtime is healthy. The delay is large enough to mislead operators into suspecting gateway or channel failures when the bottleneck is actually config validation + contract loading.

Suggested fix directions

One of these should help:

  1. Allow native loading for built dist/extensions/*/contract-api.js artifacts when they are plain .js / .mjs / .cjs files.
  2. Special-case doctor contract loading to prefer native loading for bundled built artifacts.
  3. Reduce or cache legacy doctor rule loading across short-lived CLI invocations if native loading cannot be used.

Additional notes

  • Gateway runtime was healthy after service restart.
  • The issue reproduced independently of gateway health.
  • The slowdown is visible on a fresh process and largely disappears on repeated loads in the same process due to cache reuse.

Related issue

  • Related but not identical: #62844 ([Bug]: Telegram loader/config-read bug)
  • That issue reports Telegram-related config read failures/crashes.
  • This report focuses on the non-crashing but severe cold-start slowdown in status and related CLI commands.

extent analysis

TL;DR

Allow native loading for built dist/extensions/*/contract-api.js artifacts to reduce the cold-start slowdown in openclaw status and related commands.

Guidance

  • Identify the resolvePluginLoaderJitiTryNative function and modify it to return true for bundled dist/extensions/* paths to enable native loading.
  • Consider special-casing doctor contract loading to prefer native loading for bundled built artifacts as an alternative solution.
  • Measure the performance impact of legacy doctor rule loading and explore caching or reduction strategies if native loading is not feasible.

Example

// Modified resolvePluginLoaderJitiTryNative function
function resolvePluginLoaderJitiTryNative(contractSource) {
  // Allow native loading for built dist/extensions/* paths
  if (contractSource.startsWith('dist/extensions/')) {
    return true;
  }
  // Existing logic...
}

Notes

The suggested fix directions provided in the issue report offer a good starting point for addressing the cold-start slowdown. However, the optimal solution may depend on the specific requirements and constraints of the OpenClaw project.

Recommendation

Apply the workaround by modifying the resolvePluginLoaderJitiTryNative function to allow native loading for built dist/extensions/* paths, as this is likely to provide the most significant performance improvement.

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…

Still need to ship something?

×6

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

Back to top recommendations

TRENDING