openclaw - ✅(Solved) Fix Gateway fails to start on 2026.4.5: plugin entry path escapes plugin root: ./src/channel.js [2 pull requests, 4 comments, 5 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#61682Fetched 2026-04-08 02:55:59
View on GitHub
Comments
4
Participants
5
Timeline
10
Reactions
0
Author
Timeline (top)
cross-referenced ×5commented ×4closed ×1

After upgrading from 2026.4.3 to 2026.4.5, the gateway fails to start with:

Config invalid
File: ~/.openclaw/openclaw.json
Problem:
  - <root>: read failed: Error: plugin entry path escapes plugin root: ./src/channel.js

Run: openclaw doctor --fix

openclaw doctor --fix also crashes with the same error, so there's no way to recover without rolling back.

Error Message

Config invalid File: ~/.openclaw/openclaw.json Problem:

  • <root>: read failed: Error: plugin entry path escapes plugin root: ./src/channel.js

Run: openclaw doctor --fix

Root Cause

The bundled channel plugin api.ts files (e.g. extensions/irc/api.ts, extensions/matrix/api.ts, extensions/feishu/api.ts, etc.) re-export from ./src/channel.js:

export { ircPlugin } from "./src/channel.js";

The runtime path boundary check in channel-entry-contract (resolveBundledEntryModulePath) rejects ./src/channel.js as escaping the plugin root, even though src/ is a subdirectory within the plugin.

Affected plugins: irc, matrix, feishu, bluebubbles, line, qa-channel, discord, googlechat, imessage (and likely all channel plugins using this pattern).

Fix Action

Workaround

Roll back to 2026.4.3:

git checkout <2026.4.3-commit-hash>
pnpm install --frozen-lockfile
pnpm build
openclaw gateway

PR fix notes

PR #61711: fix(gateway): resolve mattermost plugin entry path escaping plugin root

Description (problem / solution / changelog)

Summary

  • Problem: After upgrading to 2026.4.5, the gateway fails to start with a fatal error: plugin entry path escapes plugin root: ./src/channel.js. This affects the Mattermost plugin and crashes openclaw doctor --fix as well.
  • Root Cause: The Mattermost plugin's index.ts and setup-entry.ts defined their specifier directly as "./src/channel.js". While this works in the source tree, during the tsdown build process, src/channel.ts is not treated as a top-level build entry and is tree-shaken into the bundles. Consequently, in the dist output, dist/extensions/mattermost/src/channel.js does not exist. When resolveBundledEntryModulePath attempts to validate this path via openBoundaryFileSync, it fails with ENOENT, which incorrectly triggers the misleading "escapes plugin root" error message.
  • Fix: Created a channel-plugin-api.ts barrel file for the Mattermost plugin that re-exports from ./src/channel.js, and updated the specifiers in index.ts and setup-entry.ts to point to "./channel-plugin-api.js". This aligns Mattermost with the pattern used by all other channel plugins (e.g., Telegram, IRC, Discord). The barrel file is correctly built as a top-level entry by tsdown, ensuring it exists in the dist output. Additionally, added a shape guard test to prevent future regressions where specifiers directly reference src/ subdirectories.
  • What changed:
    • Added extensions/mattermost/channel-plugin-api.ts
    • Modified extensions/mattermost/index.ts
    • Modified extensions/mattermost/setup-entry.ts
    • Modified src/channels/plugins/bundled.shape-guard.test.ts
  • What did NOT change (scope boundary): No changes were made to the core plugin SDK boundary validation logic (channel-entry-contract.ts or boundary-file-read.ts), ensuring zero risk of weakening security boundaries for other plugins.

Reproduction

  1. Install OpenClaw from source or npm (version 2026.4.5).
  2. Configure the Mattermost plugin in ~/.openclaw/openclaw.json.
  3. Run openclaw gateway or openclaw doctor --fix.
  4. Observe the fatal crash: Error: plugin entry path escapes plugin root: ./src/channel.js.

Risk / Mitigation

  • Risk: The fix modifies the entry point resolution for the Mattermost plugin. If the barrel file is not built correctly, the plugin might fail to load.
  • Mitigation: The fix exactly mirrors the proven pattern used by all other bundled channel plugins. A new shape guard test (keeps bundled channel entry specifiers off src subdirectories) has been added to statically verify that no bundled plugin specifier directly references the src/ directory, preventing this class of bugs entirely.

Change Type (select all)

  • Bug fix

Scope (select all touched areas)

  • Gateway
  • Plugins (Mattermost)
  • Tests

Linked Issue/PR

Fixes #61682

Changed files

  • extensions/mattermost/channel-plugin-api.ts (added, +3/-0)
  • extensions/mattermost/index.ts (modified, +1/-1)
  • extensions/mattermost/setup-entry.ts (modified, +1/-1)
  • src/channels/plugins/bundled.shape-guard.test.ts (modified, +25/-0)

PR #61752: fix: distinguish ENOENT from boundary-escape in plugin entry errors

Description (problem / solution / changelog)

When a plugin entry file is missing from the build output, openBoundaryFileSync() returns { ok: false, reason: "path" } — but every caller threw "plugin entry path escapes plugin root," strongly implying a security boundary violation. Users investigating #61682 (Mattermost ./src/channel.js missing from dist) spent time auditing path traversal instead of checking whether the file existed.

What changed

Added describeBoundaryFileOpenFailure() in src/infra/boundary-file-read.ts that inspects both the failure reason and the underlying error code:

FailureError codeMessage
pathENOENTplugin entry file not found: <path>
pathENOTDIR / ELOOPplugin entry path error (<code>): <path>
validationplugin entry path escapes plugin root or fails alias checks: <path>
ioplugin entry I/O error (<error>): <path>

Updated all 4 call sites that previously used a hardcoded escape message:

  • src/plugin-sdk/channel-entry-contract.ts
  • src/plugins/bundled-capability-runtime.ts
  • src/plugins/loader.ts (2 sites)

Before

plugin entry path escapes plugin root or fails alias checks

(for every failure, including a simple missing file)

After

plugin entry file not found: ./src/channel.js

(when the file doesn't exist — the common case from #61682)

Tests

4 new test cases in src/infra/boundary-file-read.test.ts covering ENOENT, ENOTDIR, validation, and I/O branches.

Known limitation

resolveBoundaryFilePathGeneric() collapses resolver-side exceptions (e.g. ELOOP during symlink canonicalization) into reason: "validation" before the formatter runs. A deeper fix for that would need changes to the boundary resolution pipeline itself — left for a follow-up.

Closes #61708

Changed files

  • .agents/maintainers.md (removed, +0/-1)
  • .agents/skills/openclaw-ghsa-maintainer/SKILL.md (removed, +0/-87)
  • .agents/skills/openclaw-parallels-smoke/SKILL.md (removed, +0/-116)
  • .agents/skills/openclaw-pr-maintainer/SKILL.md (removed, +0/-75)
  • .agents/skills/openclaw-qa-testing/SKILL.md (removed, +0/-86)
  • .agents/skills/openclaw-qa-testing/agents/openai.yaml (removed, +0/-4)
  • .agents/skills/openclaw-release-maintainer/SKILL.md (removed, +0/-267)
  • .agents/skills/openclaw-test-heap-leaks/SKILL.md (removed, +0/-75)
  • .agents/skills/openclaw-test-heap-leaks/agents/openai.yaml (removed, +0/-4)
  • .agents/skills/openclaw-test-heap-leaks/scripts/heapsnapshot-delta.mjs (removed, +0/-553)
  • .agents/skills/parallels-discord-roundtrip/SKILL.md (removed, +0/-62)
  • .agents/skills/security-triage/SKILL.md (removed, +0/-111)
  • .codex (removed, +0/-0)
  • .detect-secrets.cfg (removed, +0/-45)
  • .dockerignore (removed, +0/-72)
  • .env.example (removed, +0/-80)
  • .gitattributes (removed, +0/-3)
  • .github/CODEOWNERS (removed, +0/-54)
  • .github/ISSUE_TEMPLATE/bug_report.yml (removed, +0/-148)
  • .github/ISSUE_TEMPLATE/config.yml (removed, +0/-8)
  • .github/ISSUE_TEMPLATE/feature_request.yml (removed, +0/-70)
  • .github/actionlint.yaml (removed, +0/-23)
  • .github/actions/detect-docs-changes/action.yml (removed, +0/-53)
  • .github/actions/ensure-base-commit/action.yml (removed, +0/-61)
  • .github/actions/setup-node-env/action.yml (removed, +0/-99)
  • .github/actions/setup-pnpm-store-cache/action.yml (removed, +0/-76)
  • .github/codeql/codeql-javascript-typescript.yml (removed, +0/-18)
  • .github/dependabot.yml (removed, +0/-127)
  • .github/instructions/copilot.instructions.md (removed, +0/-64)
  • .github/labeler.yml (removed, +0/-355)
  • .github/pull_request_template.md (removed, +0/-147)
  • .github/workflows/auto-response.yml (removed, +0/-534)
  • .github/workflows/ci.yml (removed, +0/-1220)
  • .github/workflows/codeql.yml (removed, +0/-137)
  • .github/workflows/control-ui-locale-refresh.yml (removed, +0/-172)
  • .github/workflows/docker-release.yml (removed, +0/-389)
  • .github/workflows/docs-sync-publish.yml (removed, +0/-70)
  • .github/workflows/docs-translate-trigger-release.yml (removed, +0/-42)
  • .github/workflows/install-smoke.yml (removed, +0/-207)
  • .github/workflows/labeler.yml (removed, +0/-877)
  • .github/workflows/macos-release.yml (removed, +0/-93)
  • .github/workflows/openclaw-npm-release.yml (removed, +0/-449)
  • .github/workflows/plugin-clawhub-release.yml (removed, +0/-276)
  • .github/workflows/plugin-npm-release.yml (removed, +0/-217)
  • .github/workflows/sandbox-common-smoke.yml (removed, +0/-64)
  • .github/workflows/stale.yml (removed, +0/-217)
  • .github/workflows/workflow-sanity.yml (removed, +0/-98)
  • .gitignore (removed, +0/-152)
  • .jscpd.json (removed, +0/-16)
  • .mailmap (removed, +0/-13)
  • .markdownlint-cli2.jsonc (removed, +0/-55)
  • .npmignore (removed, +0/-3)
  • .npmrc (removed, +0/-4)
  • .oxfmtrc.jsonc (removed, +0/-26)
  • .oxlintrc.json (removed, +0/-39)
  • .pi/extensions/diff.ts (removed, +0/-117)
  • .pi/extensions/files.ts (removed, +0/-134)
  • .pi/extensions/prompt-url-widget.ts (removed, +0/-190)
  • .pi/extensions/redraws.ts (removed, +0/-26)
  • .pi/extensions/ui/paged-select.ts (removed, +0/-82)
  • .pi/git/.gitignore (removed, +0/-2)
  • .pi/prompts/cl.md (removed, +0/-58)
  • .pi/prompts/is.md (removed, +0/-22)
  • .pi/prompts/landpr.md (removed, +0/-73)
  • .pi/prompts/reviewpr.md (removed, +0/-134)
  • .pre-commit-config.yaml (removed, +0/-157)
  • .prettierignore (removed, +0/-1)
  • .secrets.baseline (removed, +0/-13017)
  • .shellcheckrc (removed, +0/-25)
  • .swiftformat (removed, +0/-51)
  • .swiftlint.yml (removed, +0/-150)
  • .vscode/extensions.json (removed, +0/-3)
  • .vscode/settings.json (removed, +0/-22)
  • AGENTS.md (removed, +0/-321)
  • CHANGELOG.md (removed, +0/-5560)
  • CLAUDE.md (removed, +0/-1)
  • CONTRIBUTING.md (removed, +0/-217)
  • Dockerfile (removed, +0/-266)
  • Dockerfile.sandbox (removed, +0/-24)
  • Dockerfile.sandbox-browser (removed, +0/-36)
  • Dockerfile.sandbox-common (removed, +0/-48)
  • LICENSE (removed, +0/-21)
  • Makefile (removed, +0/-4)
  • README.md (removed, +0/-614)
  • SECURITY.md (removed, +0/-323)
  • Swabble/.github/workflows/ci.yml (removed, +0/-54)
  • Swabble/.gitignore (removed, +0/-33)
  • Swabble/.swiftformat (removed, +0/-8)
  • Swabble/.swiftlint.yml (removed, +0/-43)
  • Swabble/CHANGELOG.md (removed, +0/-11)
  • Swabble/LICENSE (removed, +0/-21)
  • Swabble/Package.resolved (removed, +0/-69)
  • Swabble/Package.swift (removed, +0/-55)
  • Swabble/README.md (removed, +0/-111)
  • Swabble/Sources/SwabbleCore/Config/Config.swift (removed, +0/-77)
  • Swabble/Sources/SwabbleCore/Hooks/HookExecutor.swift (removed, +0/-75)
  • Swabble/Sources/SwabbleCore/Speech/BufferConverter.swift (removed, +0/-50)
  • Swabble/Sources/SwabbleCore/Speech/SpeechPipeline.swift (removed, +0/-114)
  • Swabble/Sources/SwabbleCore/Support/AttributedString+Sentences.swift (removed, +0/-62)
  • Swabble/Sources/SwabbleCore/Support/Logging.swift (removed, +0/-41)

Code Example

Config invalid
File: ~/.openclaw/openclaw.json
Problem:
  - <root>: read failed: Error: plugin entry path escapes plugin root: ./src/channel.js

Run: openclaw doctor --fix

---

export { ircPlugin } from "./src/channel.js";

---

git checkout <2026.4.3-commit-hash>
pnpm install --frozen-lockfile
pnpm build
openclaw gateway
RAW_BUFFERClick to expand / collapse

Description

After upgrading from 2026.4.3 to 2026.4.5, the gateway fails to start with:

Config invalid
File: ~/.openclaw/openclaw.json
Problem:
  - <root>: read failed: Error: plugin entry path escapes plugin root: ./src/channel.js

Run: openclaw doctor --fix

openclaw doctor --fix also crashes with the same error, so there's no way to recover without rolling back.

Steps to Reproduce

  1. Running OpenClaw 2026.4.3 with gateway working normally
  2. Run openclaw update — updates to 2026.4.5 successfully (build passes)
  3. Run openclaw gateway — fails with the error above
  4. Run openclaw doctor --fix — same crash

Root Cause

The bundled channel plugin api.ts files (e.g. extensions/irc/api.ts, extensions/matrix/api.ts, extensions/feishu/api.ts, etc.) re-export from ./src/channel.js:

export { ircPlugin } from "./src/channel.js";

The runtime path boundary check in channel-entry-contract (resolveBundledEntryModulePath) rejects ./src/channel.js as escaping the plugin root, even though src/ is a subdirectory within the plugin.

Affected plugins: irc, matrix, feishu, bluebubbles, line, qa-channel, discord, googlechat, imessage (and likely all channel plugins using this pattern).

Workaround

Roll back to 2026.4.3:

git checkout <2026.4.3-commit-hash>
pnpm install --frozen-lockfile
pnpm build
openclaw gateway

Environment

  • macOS (Darwin 25.3.0, Mac mini)
  • OpenClaw 2026.4.5 (3885c83)
  • Node 22+
  • Source install from git (not npm)

extent analysis

TL;DR

The issue can be temporarily resolved by rolling back to OpenClaw version 2026.4.3, as the current version 2026.4.5 has a path boundary check issue affecting bundled channel plugins.

Guidance

  • The error occurs due to a change in the path boundary check in channel-entry-contract, which now rejects ./src/channel.js as escaping the plugin root.
  • To verify the issue, check if the api.ts files in the affected plugins (e.g., extensions/irc/api.ts) re-export from ./src/channel.js.
  • As a temporary workaround, roll back to version 2026.4.3 using the provided commands: git checkout <2026.4.3-commit-hash>, pnpm install --frozen-lockfile, pnpm build, and then start the gateway with openclaw gateway.
  • The openclaw doctor --fix command is not a viable solution in this case, as it crashes with the same error.

Example

No code snippet is necessary, as the issue is related to a version change and can be resolved through a rollback.

Notes

This solution assumes that the issue is indeed caused by the path boundary check change in channel-entry-contract and that rolling back to version 2026.4.3 will resolve the issue. However, this is a temporary workaround, and a permanent fix would require addressing the underlying issue in the channel-entry-contract module.

Recommendation

Apply the workaround by rolling back to version 2026.4.3, as it is the most straightforward way to resolve the issue until a permanent fix is available.

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…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING