openclaw - 💡(How to fix) Fix resolveBuiltInModelSuppression runs the same 48-plugin load twice back-to-back via independent caches [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#73731Fetched 2026-04-29 06:15:47
View on GitHub
Comments
1
Participants
2
Timeline
3
Reactions
0
Author
Timeline (top)
closed ×1commented ×1cross-referenced ×1

During a single message dispatch, the 48-bundled-provider load for "built-in model suppression" runs twice, back-to-back (~125s + ~125s = ~250s wasted) when both catalog-hook and compat-hook paths are triggered. The two paths maintain independent caches and neither sees the other's result.

Root Cause

  • resolveProviderPluginsForCatalogHooks (provider-runtime L260) caches in catalogHookProvidersCache keyed by {workspaceDir, plugins}.
  • resolveProviderPluginsForHooks (provider-runtime L63) caches in its own cacheBucket keyed by buildHookProviderCacheKey which includes providerRefs.
  • Both eventually call resolvePluginProviders with cache: false, so the loader's LRU cache is also bypassed.
  • When one path populates its cache, the other path does not benefit.

The catalog-hook path is meant for "list all providers"; the compat-hook path is for "get compat hooks for a specific resolved model". When both trigger for the same set of provider plugins, they duplicate work.

Fix Action

Fix / Workaround

Summary

During a single message dispatch, the 48-bundled-provider load for "built-in model suppression" runs twice, back-to-back (~125s + ~125s = ~250s wasted) when both catalog-hook and compat-hook paths are triggered. The two paths maintain independent caches and neither sees the other's result.

Reproduction

  1. Enable multiple agents so both catalog-hook and compat-hook paths fire (observed with two feishu bots + bot-identity retry during the same dispatch)
  2. Observe two back-to-back load-miss key=f6f6fef581 events (identical cacheKey) in the log:

Impact

Up to ~125s per dispatch when both paths fire (observed on multi-agent gateway). On single-agent dispatch only the first path runs.

Code Example

02:03:15 load-miss key=f6f6fef581
  from: at resolveProviderPluginsForCatalogHooks (provider-runtime:283)
        <- at resolveProviderBuiltInModelSuppression (provider-runtime:627)
        <- at resolveBuiltInModelSuppression (model-suppression:92)
02:05:18 load-done key=f6f6fef581 elapsedMs=123427

02:05:19 load-miss key=f6f6fef581  <-- same key, 1s after previous done
  from: at resolveProviderCompatHookPlugins (provider-runtime:343)
        <- at applyProviderResolvedModelCompatWithPlugins (provider-runtime:369)
        <- at normalizeResolvedModel (model:188)
02:07:25 load-done key=f6f6fef581 elapsedMs=125639
RAW_BUFFERClick to expand / collapse

Environment

  • openclaw 2026.4.26

Summary

During a single message dispatch, the 48-bundled-provider load for "built-in model suppression" runs twice, back-to-back (~125s + ~125s = ~250s wasted) when both catalog-hook and compat-hook paths are triggered. The two paths maintain independent caches and neither sees the other's result.

Reproduction

  1. Enable multiple agents so both catalog-hook and compat-hook paths fire (observed with two feishu bots + bot-identity retry during the same dispatch)
  2. Observe two back-to-back load-miss key=f6f6fef581 events (identical cacheKey) in the log:
02:03:15 load-miss key=f6f6fef581
  from: at resolveProviderPluginsForCatalogHooks (provider-runtime:283)
        <- at resolveProviderBuiltInModelSuppression (provider-runtime:627)
        <- at resolveBuiltInModelSuppression (model-suppression:92)
02:05:18 load-done key=f6f6fef581 elapsedMs=123427

02:05:19 load-miss key=f6f6fef581  <-- same key, 1s after previous done
  from: at resolveProviderCompatHookPlugins (provider-runtime:343)
        <- at applyProviderResolvedModelCompatWithPlugins (provider-runtime:369)
        <- at normalizeResolvedModel (model:188)
02:07:25 load-done key=f6f6fef581 elapsedMs=125639

Root Cause

  • resolveProviderPluginsForCatalogHooks (provider-runtime L260) caches in catalogHookProvidersCache keyed by {workspaceDir, plugins}.
  • resolveProviderPluginsForHooks (provider-runtime L63) caches in its own cacheBucket keyed by buildHookProviderCacheKey which includes providerRefs.
  • Both eventually call resolvePluginProviders with cache: false, so the loader's LRU cache is also bypassed.
  • When one path populates its cache, the other path does not benefit.

The catalog-hook path is meant for "list all providers"; the compat-hook path is for "get compat hooks for a specific resolved model". When both trigger for the same set of provider plugins, they duplicate work.

Suggested Fix

Either: (a) Let resolveProviderPluginsForHooks consult catalogHookProvidersCache as a fallback when its own bucket misses, or (b) Share a single result cache keyed by (workspaceDir, cfg, onlyPluginIds) at a higher level than both paths.

Impact

Up to ~125s per dispatch when both paths fire (observed on multi-agent gateway). On single-agent dispatch only the first path runs.

Related: #73729, #73728

extent analysis

TL;DR

Implement a shared cache or fallback mechanism to avoid duplicate work between catalog-hook and compat-hook paths.

Guidance

  • Identify the cache keys used by catalogHookProvidersCache and cacheBucket to understand the overlap and potential for sharing.
  • Consider implementing option (a) from the suggested fix, where resolveProviderPluginsForHooks checks catalogHookProvidersCache as a fallback.
  • Evaluate the feasibility of option (b), sharing a single result cache at a higher level, and assess the impact on performance and complexity.
  • Review the logs to verify that the duplicate load-miss events are indeed caused by the independent caches and not other factors.

Example

No code snippet is provided as the issue does not contain sufficient information to create a concrete example.

Notes

The suggested fix implies that the issue is specific to the interaction between catalog-hook and compat-hook paths, and the solution should focus on caching and cache sharing.

Recommendation

Apply workaround (a) or (b) as suggested in the issue, as it directly addresses the identified root cause and has the potential to significantly reduce the wasted time per dispatch.

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

openclaw - 💡(How to fix) Fix resolveBuiltInModelSuppression runs the same 48-plugin load twice back-to-back via independent caches [1 comments, 2 participants]