openclaw - ✅(Solved) Fix ENV OPENCLAW_BUNDLED_PLUGINS_DIR=/app/extensions causes Matrix crash loop on Node 24 (native TS loader skips .js→.ts remapping) [2 pull requests, 1 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#62044Fetched 2026-04-08 03:09:50
View on GitHub
Comments
0
Participants
1
Timeline
4
Reactions
0
Author
Participants
Timeline (top)
cross-referenced ×2closed ×1referenced ×1

The official Docker image ghcr.io/openclaw/openclaw:2026.4.5 sets OPENCLAW_BUNDLED_PLUGINS_DIR=/app/extensions, pointing to the TypeScript source directory. On Node.js v24 (bundled in this image), which has native TypeScript support enabled (process.features.typescript = true), this causes a crash loop when the Matrix plugin loads: Node 24 picks up .ts files natively but does not remap .js → .ts for static imports inside those files.

Root Cause

Root cause chain:

  • OPENCLAW_BUNDLED_PLUGINS_DIR=/app/extensions → raw TypeScript source
  • Node 24 has native TS support active — loads credentials-read.ts natively when credentials-read.js is requested
  • Node 24's native TS loader does not remap .js → .ts for static imports inside the loaded .ts file
  • TypeScript convention uses .js extensions in import statements (e.g. import ... from './account-selection.js') — Node 24 does not resolve these to their .ts counterparts
  • account-selection.js not found → crash

Fix Action

Workaround

FROM ghcr.io/openclaw/openclaw:2026.4.5
ENV OPENCLAW_BUNDLED_PLUGINS_DIR=/app/dist/extensions

Or at runtime:

docker run -e OPENCLAW_BUNDLED_PLUGINS_DIR=/app/dist/extensions ghcr.io/openclaw/openclaw:2026.4.5

PR fix notes

PR #62048: fix: use dist/extensions for OPENCLAW_BUNDLED_PLUGINS_DIR to fix Node 24 crash

Description (problem / solution / changelog)

Problem

On Node 24, process.features.typescript is true, meaning Node has native TypeScript support enabled. When OPENCLAW_BUNDLED_PLUGINS_DIR points to /app/extensions (the TypeScript source tree), Node 24 intercepts .ts file loading natively — but its native TS loader does not remap .js imports to .ts for static imports inside those files.

This causes a crash loop on startup:

Cannot find module '/app/extensions/matrix/src/account-selection.js'
imported from /app/extensions/matrix/src/credentials-read.ts

The call chain: JITI loads credentials-read.ts → inside that file, account-selection.js is imported statically → Node 24 native TS loader resolves credentials-read.ts but then tries to find account-selection.js literally (no .js→.ts remapping) → module not found → crash.

Note: the issue is not with JITI itself. JITI handles .js→.ts remapping correctly in isolation. The problem is Node 24 intercepting before JITI in this code path.

Fix

Point OPENCLAW_BUNDLED_PLUGINS_DIR to /app/dist/${OPENCLAW_BUNDLED_PLUGIN_DIR} (compiled JS) instead of /app/${OPENCLAW_BUNDLED_PLUGIN_DIR} (TypeScript source). The dist/ tree is already present in the runtime image via COPY --from=runtime-assets ... /app/dist ./dist (line 153).

Using compiled JS avoids the Node 24 native TS loader entirely for bundled plugins.

Testing

Verified on:

  • Node 24 (Ubuntu 24.04, Docker)
  • OpenClaw 2026.4.5
  • Matrix channel: no crash loop, MatrixRTCSession syncing correctly after fix

Related

Closes #62044

Changed files

  • Dockerfile (modified, +10/-3)

PR #62316: fix(docker): use built bundled plugins in runtime images

Description (problem / solution / changelog)

Summary

  • Problem: the Docker runtime image forced bundled plugin discovery to /app/extensions, which made packaged installs load raw source plugin entries instead of compiled runtime artifacts.
  • Why it matters: on Node 24 this can boot through source-only plugin paths and crash fresh containers, with Matrix surfacing first in issue #62044.
  • What changed: removed the Docker OPENCLAW_BUNDLED_PLUGINS_DIR override so packaged installs fall back to the normal resolver and use dist/extensions; updated the Dockerfile guard test; added a changelog fix entry.
  • What did NOT change (scope boundary): no plugin loader redesign, no source-runtime compatibility work, no broader plugin import refactor.

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 #62044
  • Related #50058
  • This PR fixes a bug or regression

Root Cause (if applicable)

  • Root cause: commit a2a9a553e1e03fcd6a3ec01196f3cd7b58710b7e added a Docker runtime override that pinned OPENCLAW_BUNDLED_PLUGINS_DIR to /app/extensions, bypassing the packaged-install resolver that already prefers dist/extensions.
  • Missing detection / guardrail: the Dockerfile test locked in the source-tree override instead of asserting packaged-runtime default behavior.
  • Contributing context (if known): the issue became user-visible after the Node 24 runtime image path started executing against source plugin graphs that are not the intended packaged runtime surface.

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/dockerfile.test.ts
  • Scenario the test should lock in: runtime images must not override bundled plugin discovery away from packaged defaults.
  • Why this is the smallest reliable guardrail: the regression was introduced directly in the Dockerfile and guarded by a Dockerfile-specific test.
  • Existing test that already covers this (if any): src/plugins/bundled-dir.test.ts already covers packaged-install preference for dist/extensions.
  • If no new test is added, why not: existing Dockerfile guard test was updated instead of adding a duplicate.

User-visible / Behavior Changes

Docker runtime images now use compiled bundled plugin artifacts again instead of forcing source plugin discovery.

Diagram (if applicable)

Before:
[docker runtime] -> [/app/extensions override] -> [source plugin entrypoints] -> [Node 24 source-path crash]

After:
[docker runtime] -> [default packaged resolver] -> [dist/extensions] -> [compiled plugin artifacts]

Security Impact (required)

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

Repro + Verification

Environment

  • OS: macOS
  • Runtime/container: local repo runtime; Docker packaging path
  • Model/provider: N/A
  • Integration/channel (if any): bundled Matrix plugin as first visible reproducer
  • Relevant config (redacted): default packaged bundled-plugin resolution

Steps

  1. Inspect Docker runtime image config and bundled plugin resolver behavior.
  2. Verify source bundled plugin path is forced by the Dockerfile override.
  3. Remove the override so packaged installs fall back to dist/extensions.
  4. Run targeted tests and full build.

Expected

  • Packaged Docker/runtime installs use compiled bundled plugin artifacts.

Actual

  • Before fix, Docker runtime images forced source plugin discovery.

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: pnpm test src/dockerfile.test.ts src/plugins/bundled-dir.test.ts; pnpm build
  • Edge cases checked: packaged resolver still prefers built bundled artifacts; Dockerfile no longer pins the wrong runtime env var.
  • What you did not verify: full rebuilt Docker image boot smoke.

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/No) Yes
  • Config/env changes? (Yes/No) No
  • Migration needed? (Yes/No) No
  • If yes, exact upgrade steps:

Risks and Mitigations

  • Risk: a Docker-specific workflow may have been relying on source plugin discovery.
    • Mitigation: packaged installs already prefer dist/extensions, and the built plugin manifests are the intended runtime surface.

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • Dockerfile (modified, +0/-4)
  • src/dockerfile.test.ts (modified, +7/-5)

Code Example

docker run ghcr.io/openclaw/openclaw:2026.4.5

---

Cannot find module '/app/extensions/matrix/src/account-selection.js'
imported from /app/extensions/matrix/src/matrix/credentials-read.ts

---

ENV OPENCLAW_BUNDLED_PLUGINS_DIR=/app/extensions

---

ENV OPENCLAW_BUNDLED_PLUGINS_DIR=/app/dist/extensions

---

FROM ghcr.io/openclaw/openclaw:2026.4.5
ENV OPENCLAW_BUNDLED_PLUGINS_DIR=/app/dist/extensions

---

docker run -e OPENCLAW_BUNDLED_PLUGINS_DIR=/app/dist/extensions ghcr.io/openclaw/openclaw:2026.4.5
RAW_BUFFERClick to expand / collapse

Summary

The official Docker image ghcr.io/openclaw/openclaw:2026.4.5 sets OPENCLAW_BUNDLED_PLUGINS_DIR=/app/extensions, pointing to the TypeScript source directory. On Node.js v24 (bundled in this image), which has native TypeScript support enabled (process.features.typescript = true), this causes a crash loop when the Matrix plugin loads: Node 24 picks up .ts files natively but does not remap .js → .ts for static imports inside those files.

Steps to Reproduce

  1. Run the official image with Matrix enabled (default config):
docker run ghcr.io/openclaw/openclaw:2026.4.5
  1. The container enters a crash loop immediately.

Actual Behavior

Crash loop with:

Cannot find module '/app/extensions/matrix/src/account-selection.js'
imported from /app/extensions/matrix/src/matrix/credentials-read.ts

Root cause chain:

  • OPENCLAW_BUNDLED_PLUGINS_DIR=/app/extensions → raw TypeScript source
  • Node 24 has native TS support active — loads credentials-read.ts natively when credentials-read.js is requested
  • Node 24's native TS loader does not remap .js → .ts for static imports inside the loaded .ts file
  • TypeScript convention uses .js extensions in import statements (e.g. import ... from './account-selection.js') — Node 24 does not resolve these to their .ts counterparts
  • account-selection.js not found → crash

Expected Behavior

Bundled plugins should load from /app/dist/extensions/ (compiled JS), which already exists in the image and does not trigger this issue.

Environment

ComponentValue
Imageghcr.io/openclaw/openclaw:2026.4.5
Node.jsv24.14.0 (bundled in image)
process.features.typescripttrue
Plugin affectedMatrix
OPENCLAW_BUNDLED_PLUGINS_DIR (current)/app/extensions (TS source)
OPENCLAW_BUNDLED_PLUGINS_DIR (needed)/app/dist/extensions (compiled JS)

Proposed Fix

In the official image Dockerfile, change:

ENV OPENCLAW_BUNDLED_PLUGINS_DIR=/app/extensions

to:

ENV OPENCLAW_BUNDLED_PLUGINS_DIR=/app/dist/extensions

/app/dist/extensions/ is already present in the image with compiled JavaScript plugins.

Workaround

FROM ghcr.io/openclaw/openclaw:2026.4.5
ENV OPENCLAW_BUNDLED_PLUGINS_DIR=/app/dist/extensions

Or at runtime:

docker run -e OPENCLAW_BUNDLED_PLUGINS_DIR=/app/dist/extensions ghcr.io/openclaw/openclaw:2026.4.5

Additional Notes

This does not reproduce on Node 22 — JITI handles full resolution there. The bug is triggered by the Node 24 upgrade bundled in the 2026.4.5 image.

extent analysis

TL;DR

Change the OPENCLAW_BUNDLED_PLUGINS_DIR environment variable to /app/dist/extensions to load compiled JavaScript plugins instead of TypeScript source.

Guidance

  • The issue is caused by Node.js v24 loading TypeScript files natively, but not remapping .js to .ts for static imports.
  • To fix this, update the OPENCLAW_BUNDLED_PLUGINS_DIR environment variable to point to the compiled JavaScript plugins directory (/app/dist/extensions).
  • This can be done by modifying the Dockerfile or by setting the environment variable at runtime using the -e flag with docker run.
  • Verify that the fix worked by checking that the container no longer enters a crash loop and that the Matrix plugin loads correctly.

Example

ENV OPENCLAW_BUNDLED_PLUGINS_DIR=/app/dist/extensions

Or at runtime:

docker run -e OPENCLAW_BUNDLED_PLUGINS_DIR=/app/dist/extensions ghcr.io/openclaw/openclaw:2026.4.5

Notes

This fix only applies to the ghcr.io/openclaw/openclaw:2026.4.5 image, which bundles Node.js v24. The issue does not occur on Node.js v22.

Recommendation

Apply the workaround by setting OPENCLAW_BUNDLED_PLUGINS_DIR=/app/dist/extensions to avoid the crash loop and ensure the Matrix plugin loads correctly. This is a temporary solution until the official image is updated with the fix.

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