openclaw - ✅(Solved) Fix [Bug]: Breaking change: api.registerTool() silently fails without contracts.tools since 2026.5.2 [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#77800Fetched 2026-05-06 06:21:15
View on GitHub
Comments
1
Participants
2
Timeline
4
Reactions
2
Timeline (top)
cross-referenced ×2commented ×1labeled ×1

In OpenClaw 2026.4.27 and earlier, plugins could dynamically register tools via api.registerTool() without declaring them in contracts.tools. After upgrading to 2026.5.2+, tool registration is silently rejected if contracts.tools is not declared in the manifest.

Error Message

registerTool() silently returns without registering the tool. The plugin code receives no error or warning. The only indication of failure is in the gateway logs:

  • Throw or return an error from api.registerTool() when contracts.tools is missing, so plugins can detect and handle the failure

Root Cause

In OpenClaw 2026.4.27 and earlier, plugins could dynamically register tools via api.registerTool() without declaring them in contracts.tools. After upgrading to 2026.5.2+, tool registration is silently rejected if contracts.tools is not declared in the manifest.

Fix Action

Fixed

PR fix notes

PR #77818: [AI-assisted] fix: throw on registerTool without contracts.tools instead of silent failure

Description (problem / solution / changelog)

Root Cause

api.registerTool() in src/plugins/registry.ts silently pushes a diagnostic and returns when the plugin manifest does not declare contracts.tools. The plugin's own code receives no error or warning — the only signal is a gateway-level diagnostic log (plugin must declare contracts.tools before registering agent tools) that most plugin developers never see.

This was introduced as part of the manifest-first tool contract enforcement (2026.5.2) but the enforcement path chose a non-throwing diagnostic instead of an error, making it impossible for plugins to detect the failed registration.

Fix

Replace the silent return with a throw new Error(...) in three guard paths within registerTool and registerToolMetadata:

  1. No contracts.tools declared at all — throws immediately with the plugin ID and a clear message.
  2. Tool names not in the declared contract — throws with the list of undeclared tool names.
  3. Tool metadata for undeclared tools — throws with the undeclared tool names.

The loader's existing try/catch around register(api) catches the error and records it as a plugin load failure with a diagnostic, so the plugin is properly marked as failed and the error is surfaced in logs.

Regression Test Plan

  • Existing tests in src/plugins/loader.test.ts ("rejects plugin tool registration without manifest tool ownership" and "rejects plugin tool names outside the manifest tool contract") updated to match the new error message format.
  • All 123 tests in loader.test.ts pass.
  • The throw does not change the external contract: registerTool return type remains void, and the loader already handles thrown errors from plugin register() calls.

Security Impact

None. This change makes a silent failure loud — it does not alter any security boundary or access control.

Closes #77800

Changed files

  • src/plugins/loader.test.ts (modified, +4/-2)
  • src/plugins/registry.ts (modified, +9/-3)

PR #78084: fix: support dynamic plugin tool contracts

Description (problem / solution / changelog)

Summary

Fixes dynamic plugin tool ownership without reverting the manifest-first plugin contract.

Plugins still must declare contracts.tools, but they can now declare a bounded terminal wildcard namespace such as acme_*. Runtime api.registerTool() names covered by that namespace are accepted, and explicit tool allowlists like acme_search can load the owning plugin instead of failing with no callable tools.

Changes

  • Add terminal wildcard matching for plugin tool contracts (prefix_*).
  • Keep bare * from becoming catch-all ownership.
  • Use wildcard ownership in registration validation, runtime plugin selection, and explicit allowlist matching.
  • Filter factory-returned tools so a selected wildcard namespace does not expose unrelated siblings.
  • Add loader and plugin tool resolution regression tests.
  • Document dynamic namespace ownership in plugin manifest docs.

Testing

  • PATH="/tmp/openclaw-pnpm-shim:$PATH" pnpm vitest run src/plugins/loader.test.ts src/plugins/tools.optional.test.ts — passed, 183 tests.
  • git diff --check — passed.
  • PATH="/tmp/openclaw-pnpm-shim:$PATH" node scripts/check-changed.mjs — passed through pairing store guard, then SIGKILLed before/at final pairing-account guard on this host. Standalone PATH="/tmp/openclaw-pnpm-shim:$PATH" node scripts/check-pairing-account-scope.mjs passed.

Fixes #77800

Changed files

  • docs/plugins/manifest.md (modified, +3/-1)
  • src/plugins/loader.test.ts (modified, +42/-0)
  • src/plugins/tool-contracts.ts (modified, +36/-2)
  • src/plugins/tools.optional.test.ts (modified, +40/-0)
  • src/plugins/tools.ts (modified, +32/-7)

Code Example

plugin must declare contracts.tools before registering agent tools (plugin=xxx)

---
RAW_BUFFERClick to expand / collapse

Bug type

Regression (worked before, now fails)

Beta release blocker

No

Summary

In OpenClaw 2026.4.27 and earlier, plugins could dynamically register tools via api.registerTool() without declaring them in contracts.tools. After upgrading to 2026.5.2+, tool registration is silently rejected if contracts.tools is not declared in the manifest.

Steps to reproduce

Steps to reproduce:

  1. Create a plugin that calls api.registerTool() at startup without contracts.tools in the manifest
  2. Start OpenClaw
  3. Plugin logs show successful registration (e.g. "registered 12 tools")
  4. Open any agent session — the tools are not visible
  5. Cron jobs referencing these tools fail with: No callable tools remain after resolving explicit tool allowlist; no registered tools matched

Expected behavior

Tools registered via api.registerTool() should be available to agents, consistent with behavior in 2026.4.27.

Actual behavior

registerTool() silently returns without registering the tool. The plugin code receives no error or warning. The only indication of failure is in the gateway logs:

plugin must declare contracts.tools before registering agent tools (plugin=xxx)

OpenClaw version

2026.5.2

Operating system

macOS

Install method

No response

Model

opus 4-6

Provider / routing chain

openclaw

Additional provider/model setup details

No response

Logs, screenshots, and evidence

Impact and severity

No response

Additional information

Why this is a bug (not just a breaking change):

  1. Silent failureapi.registerTool() returns without throwing, giving the plugin no way to detect the failure
  2. Misleading logs — the plugin's own success log fires after the failed registerTool() calls, making it appear registration succeeded
  3. No migration path for dynamic plugins — plugins that fetch tool definitions from external APIs at runtime cannot know tool names at manifest-write time, making contracts.tools impossible to maintain statically

Environment:

  • Broken since: 2026.5.2
  • Last working version: 2026.4.27
  • Current version: 2026.5.3-1

Suggested fix:

Either:

  • Throw or return an error from api.registerTool() when contracts.tools is missing, so plugins can detect and handle the failure
  • Support glob patterns in contracts.tools (e.g. "xxx_*") to accommodate dynamic tool namespaces
  • Provide a migration guide / deprecation warning in 2026.5.2 release notes

extent analysis

TL;DR

Update the plugin manifest to include contracts.tools or modify api.registerTool() to handle dynamic tool registration.

Guidance

  • Verify that the contracts.tools field is present in the plugin manifest and contains the expected tool names.
  • Consider modifying the plugin to declare contracts.tools with a glob pattern (if supported) to accommodate dynamic tool namespaces.
  • If using a version prior to 2026.5.2, ensure that the plugin's api.registerTool() calls are successful and tools are visible to agents.
  • Review the OpenClaw release notes for any migration guides or deprecation warnings related to tool registration.

Example

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

Notes

The suggested fix implies that the api.registerTool() method should be modified to either throw an error or return a value indicating failure when contracts.tools is missing. However, the exact implementation details are not provided.

Recommendation

Apply a workaround by updating the plugin manifest to include contracts.tools with the expected tool names, as this is the most straightforward solution given the current information.

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…

FAQ

Expected behavior

Tools registered via api.registerTool() should be available to agents, consistent with behavior in 2026.4.27.

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 - ✅(Solved) Fix [Bug]: Breaking change: api.registerTool() silently fails without contracts.tools since 2026.5.2 [2 pull requests, 1 comments, 2 participants]