-
-
Notifications
You must be signed in to change notification settings - Fork 80.7k
Plugin loader: silent failures on legacy/invalid plugin contracts cost hours of debugging #78301
Copy link
Copy link
Open
Labels
P2Normal backlog priority with limited blast radius.Normal backlog priority with limited blast radius.clawsweeper:fix-shape-clearClawSweeper found a clear likely implementation shape for this issue.ClawSweeper found a clear likely implementation shape for this issue.clawsweeper:needs-maintainer-reviewClawSweeper marked this issue as needing maintainer review before automation.ClawSweeper marked this issue as needing maintainer review before automation.clawsweeper:needs-product-decisionClawSweeper marked this issue as needing a product or behavior decision.ClawSweeper marked this issue as needing a product or behavior decision.clawsweeper:needs-security-reviewClawSweeper marked this issue as needing security-sensitive review.ClawSweeper marked this issue as needing security-sensitive review.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.ClawSweeper does not recommend queueing a new automated fix PR for this issue.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.ClawSweeper found a high-confidence source-level issue reproduction.impact:otherThis issue has meaningful maintainer-visible impact outside the owned taxonomy.This issue has meaningful maintainer-visible impact outside the owned taxonomy.impact:securitySecurity boundary, credential, authz, sandbox, or sensitive-data risk.Security boundary, credential, authz, sandbox, or sensitive-data risk.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.Very strong issue quality with high-confidence source-level or clear reproduction.
Description
Metadata
Metadata
Assignees
Labels
P2Normal backlog priority with limited blast radius.Normal backlog priority with limited blast radius.clawsweeper:fix-shape-clearClawSweeper found a clear likely implementation shape for this issue.ClawSweeper found a clear likely implementation shape for this issue.clawsweeper:needs-maintainer-reviewClawSweeper marked this issue as needing maintainer review before automation.ClawSweeper marked this issue as needing maintainer review before automation.clawsweeper:needs-product-decisionClawSweeper marked this issue as needing a product or behavior decision.ClawSweeper marked this issue as needing a product or behavior decision.clawsweeper:needs-security-reviewClawSweeper marked this issue as needing security-sensitive review.ClawSweeper marked this issue as needing security-sensitive review.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.ClawSweeper does not recommend queueing a new automated fix PR for this issue.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.ClawSweeper found a high-confidence source-level issue reproduction.impact:otherThis issue has meaningful maintainer-visible impact outside the owned taxonomy.This issue has meaningful maintainer-visible impact outside the owned taxonomy.impact:securitySecurity boundary, credential, authz, sandbox, or sensitive-data risk.Security boundary, credential, authz, sandbox, or sensitive-data risk.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.Very strong issue quality with high-confidence source-level or clear reproduction.
Type
Fields
Priority
None yet
While debugging why
@tencent-weixin/[email protected]was failing on a 2026.5.4 host, I hit two cases where the plugin loader silently tolerates plugin-authoring bugs that surface much later as opaque runtime errors. Both could have been caught at plugin load time with a clear message naming the plugin and the contract violated.This is a request for better diagnostics — not for relaxing the underlying defenses, which are correct.
Case 1 — Strict undici dispatcher rejects manual
Content-Length, but the cause is buriedOpenClaw installs a hardened global undici dispatcher (visible via
ensureGlobalUndiciEnvProxyDispatcher/fetchWithSsrFGuardinopenclaw/plugin-sdk/infra-runtime) that correctly rejects plugin-suppliedContent-Lengthheaders withUND_ERR_INVALID_ARG: invalid content-length header. This is good — manualContent-Lengthenables request-smuggling vectors when the value drifts from the actual transmitted bytes.Problem: the rejection bubbles up as a generic
TypeError: fetch failed. The actual cause is only visible if the plugin inspectserr.cause. Most plugin code doesString(err)and the signal is lost. End result for the operator: a silent restart loop with no actionable log line.Repro (real): the Tencent plugin's
dist/src/api/api.jsline 164 manually setsContent-Length. Every API call (getUpdates, login, send) fails synchronously. Surface symptom isFailed to start login: TypeError: fetch failedand aWeixin runtime initialization timeoutloop. The actual root cause took bisecting through the plugin's import graph to find — the openclaw SDK import was what flipped fetch behavior.Suggested improvement: in
fetchWithRuntimeDispatcher/fetchWithSsrFGuard(or wherever plugin requests funnel through), strip and warn on plugin-suppliedContent-Lengthwith a one-time deprecation log per plugin:This converts a hard failure into a soft signal that names the offending plugin.
Case 2 — Plugins without
"runtime"in manifest get no runtime injection and no warning@openclaw/[email protected]declares in its plugin manifest:…and the host correctly calls
setWhatsAppRuntimeon load.@tencent-weixin/[email protected]does not declareruntimein itsopenclaw.plugin.jsonorpackage.json#openclaw. Itsregister(api)readsapi.runtime(the legacy contract) and only callssetWeixinRuntime(api.runtime)when truthy. On 2026.5.4 it isn't, sopluginRuntimestaysnull,waitForWeixinRuntimetimes out at 10s, and the channel enters a permanent restart loop withWeixin runtime initialization timeout— logged by the plugin, not the host.The loader is silent about this mismatch. There's no host-side diagnostic at plugin-load time that says this plugin uses the legacy runtime contract; runtime injection skipped.
Suggested improvement: after calling
register(api), if the plugin's manifest doesn't declareruntimeAND the host didn't passruntimeintoapi, emit a one-time deprecation warning per plugin:Bonus — Migration guide
A Plugin author's migration guide: 2026.4.x → 2026.5.x linked from the relevant sections of
plugin-sdkwould close the loop. The Tencent plugin (Tencent/openclaw-weixinon GitHub) hasn't migrated, possibly because the migration was never visible to them. A short section showing the before/after forruntime: {specifier, exportName}would help every external plugin author.Environment
@tencent-weixin/[email protected](will file the actual plugin bugs atTencent/openclaw-weixinseparately)