fix(runtime): three stability fixes for SIGUSR1 restart loop and BYOK model override#915
Merged
fix(runtime): three stability fixes for SIGUSR1 restart loop and BYOK model override#915
Conversation
Move the isServiceDisabled + enableService check to the very top of LaunchdManager.installService so it runs even when the service is already registered with unchanged plist content. The PR #836 fix only ran the disabled check on the bootstrap path, which means upgrades that don't change the plist hit the early-return and never clear legacy `launchctl unload -w` flags. As a result, OpenClaw's own SIGUSR1 self-restart flow tries `launchctl bootstrap` and fails with "Bootstrap failed: 5" on every reload, draining the gateway for ~11s and rejecting user requests with "Gateway is draining for restart". `launchctl enable` is idempotent, so calling it on every install is safe.
Build plugins.allow via sort + dedup so the output array is fully deterministic regardless of channel insertion order or transient status flaps. Without this, every time a channel briefly flips status (e.g. weixin account probe) the resulting allow array's order changes, OpenClaw treats it as a config change, and triggers a SIGUSR1 in-process restart with an 11s gateway drain window. One affected user hit 8 SIGUSR1 restarts in a single day.
…viders Add the set of configured provider keys to resolveAvailableRuntimeModel and trust any desiredRef whose provider exists in compiled.models.providers, even when the provider's explicit models[] list is empty. Without this, a BYOK Anthropic user who selected \`anthropic/claude-opus-4-6\` but never explicitly added models to the provider's allowlist would silently get their selection overridden to \`link/gemini-3-flash-preview\` (the default link model) on every doSync. OpenClaw's resolveModelWithRegistry has a generic-fallback path that builds a synthetic model entry whenever providerConfig is present, so the request still goes through correctly with the user's chosen model.
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
mrcfps
approved these changes
Apr 8, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Three small surgical fixes for runtime stability bugs found while diagnosing user reports today. Each is a separate commit so they can be reviewed (or split) independently.
Why
How
Commit 1 — `fix(desktop): always clear launchd disabled override at install time`
Move the `isServiceDisabled` + `enableService` block to the very top of `LaunchdManager.installService`, before the `isRegistered` early-return. `launchctl enable` is idempotent so calling it on every install is safe.
Commit 2 — `fix(controller): sort plugins.allow to prevent spurious gateway restarts`
Change `compilePlugins` to emit `allow` via `Array.from(new Set([...connectedPluginIds, ...platformPluginIds])).sort()` so the output is fully deterministic regardless of input order.
Commit 3 — `fix(controller): trust user model selection under configured BYOK providers`
Pass `configuredProviderKeys` (set of provider keys in `compiled.models.providers`) to `resolveAvailableRuntimeModel`. Add a new rule: trust any `desiredRef` whose provider key is configured. OpenClaw's `resolveModelWithRegistry` has a generic-fallback path that builds a synthetic model entry when `providerConfig` is present, so the request still goes through with the user's chosen model.
Affected areas
Checklist
Notes for reviewers