openclaw - ✅(Solved) Fix [Bug]: Workspace plugin HTTP routes register successfully but dispatcher returns 404 on all paths [1 pull requests, 2 comments, 3 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#73747Fetched 2026-04-29 06:15:39
View on GitHub
Comments
2
Participants
3
Timeline
6
Reactions
0
Author
Timeline (top)
commented ×2cross-referenced ×1labeled ×1mentioned ×1

A workspace plugin's api.registerHttpRoute(...) call succeeds, the route appears in the plugin registry per openclaw plugins inspect, and the registration is logged at startup. However the HTTP dispatcher returns 404 for all requests to the registered path and the handler never fires.

Root Cause

A workspace plugin's api.registerHttpRoute(...) call succeeds, the route appears in the plugin registry per openclaw plugins inspect, and the registration is logged at startup. However the HTTP dispatcher returns 404 for all requests to the registered path and the handler never fires.

Fix Action

Fix / Workaround

A workspace plugin's api.registerHttpRoute(...) call succeeds, the route appears in the plugin registry per openclaw plugins inspect, and the registration is logged at startup. However the HTTP dispatcher returns 404 for all requests to the registered path and the handler never fires.

Per Plugin Internals documentation (https://docs.openclaw.ai/plugins/architecture#gateway-http-routes), api.registerHttpRoute(...) should attach the route to the gateway HTTP dispatcher and the registered handler should be invoked when the path is requested. Same plugin worked previously on a local Mac Docker setup before migrating to Hetzner.

anthropic/claude-sonnet-4-6 (not relevant to this bug — issue is in HTTP route dispatch, not inference)

PR fix notes

PR #73877: fix(plugins): beta blocker - Workspace plugin HTTP routes return 404

Description (problem / solution / changelog)

Summary

Describe the problem and fix in 2–5 bullets:

  • Problem: Workspace plugin HTTP routes register successfully but the HTTP dispatcher returns a 404 for all requests to the registered path.
  • Why it matters: It blocks plugins from receiving inbound webhooks (e.g., Stripe, Gmail push notifications, Slack callbacks) since the gateway silently fails to dispatch them to the plugin.
  • What changed: Removed the unconditional pinActivePluginHttpRouteRegistry(params.pluginRegistry) in createGatewayRuntimeState so the HTTP route registry surface can properly sync and accept runtime updates.
  • What did NOT change (scope boundary): The channel registry pinning remains intact. No changes were made to how routes are parsed, authorized, or executed.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #73747
  • Related #
  • This PR fixes a bug or regression

Root Cause (if applicable)

  • Root cause: The gateway runtime was unconditionally pinning the HTTP route registry surface at startup. When dynamic plugins loaded later, setActivePluginRegistry triggered syncTrackedSurface, which explicitly bails out if surface.pinned is true. As a result, the dispatcher always resolved the empty/stale startup route registry.
  • Missing detection / guardrail: There was no integration test validating that dynamically loaded plugins (which register routes post-startup) have their HTTP routes correctly resolved by the gateway HTTP dispatcher.
  • Contributing context (if known): Likely copied from or related to the channel registry pinning logic, which is necessary to prevent config-schema reads from evicting channel plugins.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: src/gateway/server-plugin-bootstrap.dynamic-routes.integration.test.ts
  • Scenario the test should lock in: Ensure that if a plugin registers an HTTP route after createGatewayRuntimeState is run (i.e. dynamic plugin initialization), resolveActivePluginHttpRouteRegistry returns the updated registry containing the new route.
  • Why this is the smallest reliable guardrail: It specifically verifies that the registry syncing logic (setActivePluginRegistry) propagates routes to the active dispatcher state.
  • Existing test that already covers this (if any): N/A
  • If no new test is added, why not: New test was added.

User-visible / Behavior Changes

None (Restores intended documented API functionality for workspace plugins).

Diagram (if applicable)

N/A

Security Impact (required)

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? No
  • Data access scope changed? No
  • If any Yes, explain risk + mitigation: N/A

Repro + Verification

Environment

  • OS: Ubuntu 24.04 (Host)
  • Runtime/container: Docker, Node 24.14.0
  • Model/provider: N/A
  • Integration/channel (if any): Workspace Plugin
  • Relevant config (redacted): N/A

Steps

  1. Create a workspace plugin that registers an HTTP route on startup using api.registerHttpRoute({ path: "/plugins/webhooks/gmail-push", auth: "plugin", match: "exact", handler })
  2. Start OpenClaw in Docker.
  3. Make a POST request to /plugins/webhooks/gmail-push.

Expected

  • The plugin handler receives the request and executes correctly.

Actual

  • The gateway responds with 404 Not Found.

Evidence

Attach at least one:

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

What you personally verified (not just CI), and how:

  • Verified scenarios: I verified the gateway dispatch resolution logic manually using scripts that simulate the request path context logic to confirm the route registry wasn't being updated due to pinning.
  • Edge cases checked: Verified that removing the pinning doesn't impact pinActivePluginChannelRegistry, which correctly remains conditionally pinned.
  • What you did not verify: I didn't verify an end-to-end webhook provider (e.g. Stripe webhook), but verified that the dispatcher maps the route registry successfully.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? Yes
  • Config/env changes? No
  • Migration needed? No
  • If yes, exact upgrade steps: N/A

Risks and Mitigations

  • Risk: HTTP routes might be swapped or cleared unexpectedly if another registry reset happens.
    • Mitigation: The HTTP route registry is designed to be hot-swappable dynamically Workspace plugin unloads/reloads will resync the correct surface registry.

Changed files

  • src/gateway/server-plugin-bootstrap.dynamic-routes.integration.test.ts (added, +88/-0)
  • src/gateway/server-runtime-state.ts (modified, +0/-1)

Code Example

Plugin registration log on every startup:
[gmail-push] Webhook registered at /plugins/webhooks/gmail-push
[gmail-push] gmail_send tool registered

openclaw plugins inspect gmail-push output:
Status: loaded
Format: openclaw
Source: ~/.openclaw/workspace/plugins/gmail-push/index.js
Origin: config
Version: 1.0.0
Shape: non-capability
Capability mode: none
Legacy before_agent_start: no
Tools: gmail_send
HTTP routes: 1

curl test from inside container:
$ curl -X POST http://localhost:18789/plugins/webhooks/gmail-push
HTTP/1.1 404 Not Found
Content-Type: text/plain; charset=utf-8
Not Found

Gateway logs after the curl test contain no handler invocation log line. Tested with both /api/webhooks/gmail-push and /plugins/webhooks/gmail-push paths, both return 404 with handler never firing. Tested with auth: "plugin" and auth: "gateway" — same result.
RAW_BUFFERClick to expand / collapse

Bug type

Behavior bug (incorrect output/state without crash)

Beta release blocker

No

Summary

A workspace plugin's api.registerHttpRoute(...) call succeeds, the route appears in the plugin registry per openclaw plugins inspect, and the registration is logged at startup. However the HTTP dispatcher returns 404 for all requests to the registered path and the handler never fires.

Steps to reproduce

  1. Place a workspace plugin at ~/.openclaw/workspace/plugins/gmail-push/index.js that calls api.registerHttpRoute({ path: "/plugins/webhooks/gmail-push", auth: "plugin", match: "exact", handler }) with a handler containing a console.log statement.
  2. Start OpenClaw 2026.4.26 in Docker, container fully restarted.
  3. Confirm gateway logs show "[gmail-push] Webhook registered at /plugins/webhooks/gmail-push" at startup.
  4. Confirm "openclaw plugins inspect gmail-push" shows "HTTP routes: 1".
  5. Run "curl -X POST http://localhost:18789/plugins/webhooks/gmail-push" from inside the container.
  6. Observe HTTP 404 response and absence of any handler log line in gateway logs.

Expected behavior

Per Plugin Internals documentation (https://docs.openclaw.ai/plugins/architecture#gateway-http-routes), api.registerHttpRoute(...) should attach the route to the gateway HTTP dispatcher and the registered handler should be invoked when the path is requested. Same plugin worked previously on a local Mac Docker setup before migrating to Hetzner.

Actual behavior

HTTP request to the registered path returns 404 Not Found. The handler is never invoked - no console.log line from the handler appears in gateway logs. This occurs despite the plugin loading successfully (Status: loaded), the route appearing in the plugin registry (HTTP routes: 1), and the registration being logged at startup ([gmail-push] Webhook registered at /plugins/webhooks/gmail-push).

OpenClaw version

version 2026.4.26

Operating system

Hetzner CPX31, Ubuntu 24.04 (host); Node 24.14.0 inside container

Install method

Docker, openclaw:browser custom image built from ghcr.io/openclaw/openclaw:latest base via custom Dockerfile.browser

Model

anthropic/claude-sonnet-4-6 (not relevant to this bug — issue is in HTTP route dispatch, not inference)

Provider / routing chain

Not applicable — bug is in plugin HTTP route dispatcher, not inference path

Additional provider/model setup details

NOT_ENOUGH_INFO

Logs, screenshots, and evidence

Plugin registration log on every startup:
[gmail-push] Webhook registered at /plugins/webhooks/gmail-push
[gmail-push] gmail_send tool registered

openclaw plugins inspect gmail-push output:
Status: loaded
Format: openclaw
Source: ~/.openclaw/workspace/plugins/gmail-push/index.js
Origin: config
Version: 1.0.0
Shape: non-capability
Capability mode: none
Legacy before_agent_start: no
Tools: gmail_send
HTTP routes: 1

curl test from inside container:
$ curl -X POST http://localhost:18789/plugins/webhooks/gmail-push
HTTP/1.1 404 Not Found
Content-Type: text/plain; charset=utf-8
Not Found

Gateway logs after the curl test contain no handler invocation log line. Tested with both /api/webhooks/gmail-push and /plugins/webhooks/gmail-push paths, both return 404 with handler never firing. Tested with auth: "plugin" and auth: "gateway" — same result.

Impact and severity

Affected: Any workspace plugin attempting to register HTTP routes via api.registerHttpRoute() in OpenClaw 2026.4.24-2026.4.26 on Docker Severity: High - blocks plugin functionality entirely for any plugin requiring webhook reception Frequency: 100% reproducible across all tested paths and methods Consequence: Workspace plugins cannot receive inbound webhooks (Gmail Pub/Sub notifications, Stripe webhooks, third-party callbacks, etc.) despite successful registration. Plugin appears healthy in all diagnostic tools but webhooks silently fail.

Additional information

Triaged on Discord with @Krill who recommended filing this issue after confirming: 1) update from 2026.4.24 to 2026.4.26 did not resolve, 2) handler test with explicit log line confirmed handler is never invoked, 3) path convention change from /api/webhooks/* to /plugins/webhooks/* did not resolve.

Plugin code uses the documented API exactly as shown in https://docs.openclaw.ai/plugins/architecture#gateway-http-routes. registerHttpRoute is confirmed present in /app/dist/ and used by official extensions (webhooks, slack, diffs, nostr).

Last known good version not determined - same plugin worked on local Mac Docker setup prior to Hetzner migration but exact OpenClaw version at that time not recorded.

extent analysis

TL;DR

The issue is likely due to a misconfiguration or incompatibility in the OpenClaw Docker setup, causing the registered HTTP route to not be dispatched correctly, resulting in a 404 error.

Guidance

  • Verify that the api.registerHttpRoute call is correctly registering the route by checking the plugin registry output and the gateway logs for the registration message.
  • Check the Docker container's network configuration to ensure that the HTTP requests are being routed correctly to the OpenClaw gateway.
  • Test the plugin with a different authentication method (e.g., "gateway" instead of "plugin") to see if the issue is authentication-related.
  • Compare the Docker setup and configuration between the local Mac environment and the Hetzner environment to identify any differences that might be causing the issue.

Example

No code snippet is provided as the issue seems to be related to the environment setup rather than the plugin code itself.

Notes

The issue might be specific to the OpenClaw version (2026.4.26) or the Docker setup on Hetzner, and further investigation is needed to determine the root cause.

Recommendation

Apply a workaround by testing the plugin with a different OpenClaw version or Docker setup to isolate the issue, as the problem seems to be environment-specific rather than a plugin code issue.

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

Per Plugin Internals documentation (https://docs.openclaw.ai/plugins/architecture#gateway-http-routes), api.registerHttpRoute(...) should attach the route to the gateway HTTP dispatcher and the registered handler should be invoked when the path is requested. Same plugin worked previously on a local Mac Docker setup before migrating to Hetzner.

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]: Workspace plugin HTTP routes register successfully but dispatcher returns 404 on all paths [1 pull requests, 2 comments, 3 participants]