Skip to content

fix(controller): batch skillhub sync to prevent OpenClaw restart loop#1074

Merged
lefarcen merged 7 commits intomainfrom
fix/batch-skillhub-sync
Apr 13, 2026
Merged

fix(controller): batch skillhub sync to prevent OpenClaw restart loop#1074
lefarcen merged 7 commits intomainfrom
fix/batch-skillhub-sync

Conversation

@lefarcen
Copy link
Copy Markdown
Collaborator

@lefarcen lefarcen commented Apr 13, 2026

What

Batch skill installation syncs and make langfuse-tracer always-allowed to prevent OpenClaw restart loops during initial bootstrap.

Why

During initial bootstrap on a fresh install, each skill installation individually triggered onSyncNeeded → syncAll → doSync → openclaw.json write. With 10+ skills installing sequentially, this caused a sustained OpenClaw restart loop (~30-90s per restart), leaving the agent session permanently unavailable and the UI stuck on "agent starting".

Additionally, langfuse-tracer was conditionally added to plugins.allow based on analyticsEnabled. On first boot this value transitions from undefined to true, mutating plugins.allow and triggering a full gateway restart (~11s), compounding the restart loop.

Diagnosed from a Windows user's diagnostics bundle: OpenClaw crashed and restarted 5+ times in 18 minutes, each time with a different PID, and the desktop created 5 separate webviews for the agent session that all became stale.

How

Commit 1: batch skillhub sync

  • Added an onIdle callback to InstallQueue that fires only when the queue fully drains (no active or pending items) after at least one successful completion.
  • Moved the onSyncNeeded() call from the per-item onComplete to onIdle.
  • onComplete still records each install in skillDb immediately (no data loss).
  • Single-skill installs behave identically: queue has 1 item → completes → queue empty → onIdle fires immediately.
  • The existing 100ms debounce in syncAll() and the ConfigWriter skip-if-unchanged guard remain as secondary protections.

Commit 2: langfuse-tracer always-allow

  • Moved langfuse-tracer to the unconditional always-allow list in plugins.allow.
  • Analytics preference now toggles only entries.enabled (hot-reload path) instead of mutating plugins.allow (full restart path).

Affected areas

  • Controller (backend / API)

Checklist

  • pnpm typecheck passes
  • pnpm lint passes
  • pnpm test passes
  • pnpm generate-types run (if API routes/schemas changed) — N/A

The version was accidentally downgraded to 0.1.10 for local nightly
update testing and merged to main. Restore to 0.1.11.
During initial bootstrap, each skill installation triggered an
individual config sync → openclaw.json write → OpenClaw full process
restart. With 10+ skills installing sequentially, this caused a
sustained restart loop where the agent session never stabilized,
leaving the UI stuck on "agent starting".

Move the onSyncNeeded trigger from InstallQueue's per-item onComplete
callback to a new onIdle callback that fires only when the queue fully
drains. This batches N skill installs into a single config sync while
preserving immediate sync for single-skill installs (queue drains
right after the one item completes).
@sentry
Copy link
Copy Markdown

sentry bot commented Apr 13, 2026

Codecov Report

❌ Patch coverage is 79.16667% with 5 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
.../controller/src/services/skillhub/install-queue.ts 70.58% 5 Missing ⚠️

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 59297e3868

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/controller/src/services/skillhub/install-queue.ts
@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages bot commented Apr 13, 2026

Deploying nexu-docs with  Cloudflare Pages  Cloudflare Pages

Latest commit: 54435af
Status: ✅  Deploy successful!
Preview URL: https://3858380b.nexu-docs.pages.dev
Branch Preview URL: https://fix-batch-skillhub-sync.nexu-docs.pages.dev

View logs

…estart

langfuse-tracer was conditionally added to plugins.allow based on
analyticsEnabled. On first boot or when the preference changed, this
mutated plugins.allow, which OpenClaw treats as a full gateway restart
(~11s drain + process restart on Windows).

Move langfuse-tracer to the unconditional always-allow list and use
the entries.enabled flag to toggle it. This way analytics preference
changes only flip the enabled flag (hot-reload path) instead of
mutating plugins.allow (full restart path).
@lefarcen lefarcen force-pushed the fix/batch-skillhub-sync branch from 54435af to 02e7354 Compare April 13, 2026 11:38
The update banner's "restart & install" button silently did nothing
because the renderer-side install() checked applyMode before calling
IPC. If the capability was fetched before updateManager initialized,
applyMode was "none" and the guard blocked the call permanently.

Remove the redundant guard — the main process IPC handler already
has its own null check on updateManager. The button is only visible
when the update is in "ready" state, so the install action is always
valid at that point.
@lefarcen lefarcen merged commit 7a03c2b into main Apr 13, 2026
28 of 30 checks passed
@lefarcen lefarcen mentioned this pull request Apr 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants