openclaw - 💡(How to fix) Fix Plugin register fails with ENOTEMPTY in openclaw-unknown-* shadow runtime-deps dir on every gateway boot [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#72528Fetched 2026-04-28 06:34:53
View on GitHub
Comments
2
Participants
3
Timeline
3
Reactions
1
Timeline (top)
commented ×2closed ×1

On every ai.openclaw.gateway launch, the plugin loader fails to register the bundled Telegram plugin (and several other channels) with ENOTEMPTY. Two related directories live under ~/.openclaw/plugin-runtime-deps/:

  • openclaw-2026.4.24-02f98c7ef353/ — the expected versioned dir
  • openclaw-unknown-2018ccba5afc/ — a shadow dir with unknown instead of a version. This appears to come from a version-detection fallback during install, and once it exists, every subsequent boot stages new plugin content into it but cannot complete because the destination tree already exists.

Trashing the entire ~/.openclaw/plugin-runtime-deps/ directory and restarting the gateway recreates the same broken pair immediately on first boot — so this isn't stale state from a prior install. The install logic itself produces the broken state.

Error Message

[plugins] telegram failed during register from /…/node_modules/openclaw/dist/extensions/telegram/index.js: Error: ENOTEMPTY, Directory not empty: /Users/<user>/.openclaw/plugin-runtime-deps/openclaw-unknown-2018ccba5afc/dist/extensions/node_modules/openclaw/plugin-sdk '/Users/<user>/.openclaw/plugin-runtime-deps/openclaw-unknown-2018ccba5afc/dist/extensions/node_modules/openclaw/plugin-sdk'

Root Cause

  • openclaw-2026.4.24-02f98c7ef353/ — the expected versioned dir
  • openclaw-unknown-2018ccba5afc/ — a shadow dir with unknown instead of a version. This appears to come from a version-detection fallback during install, and once it exists, every subsequent boot stages new plugin content into it but cannot complete because the destination tree already exists.

Fix Action

Fix / Workaround

  • The bundled Telegram plugin fails to register entirely; any code path using openclaw gateway call chat.send or the openclaw-mediated Telegram delivery fails.
  • Workaround: applications that need Telegram delivery can bypass the plugin and curl https://api.telegram.org/bot<token>/sendMessage directly. We've been doing this in our integration successfully.
  • The gateway itself otherwise functions; openclaw status still produces output, just with the plugin errors prepended.

Code Example

[plugins] telegram failed during register from
  //node_modules/openclaw/dist/extensions/telegram/index.js:
  Error: ENOTEMPTY, Directory not empty:
    /Users/<user>/.openclaw/plugin-runtime-deps/openclaw-unknown-2018ccba5afc/dist/extensions/node_modules/openclaw/plugin-sdk
    '/Users/<user>/.openclaw/plugin-runtime-deps/openclaw-unknown-2018ccba5afc/dist/extensions/node_modules/openclaw/plugin-sdk'

---

[plugins] telegram failed during register from
  //node_modules/openclaw/dist/extensions/telegram/index.js:
  Error: ENOTEMPTY: directory not empty, rename
    '/Users/<user>/.openclaw/plugin-runtime-deps/openclaw-unknown-2018ccba5afc/dist/extensions/.plugin-telegram-pgHesQ/plugin'
    '/Users/<user>/.openclaw/plugin-runtime-deps/openclaw-unknown-2018ccba5afc/dist/extensions/telegram'
RAW_BUFFERClick to expand / collapse

Summary

On every ai.openclaw.gateway launch, the plugin loader fails to register the bundled Telegram plugin (and several other channels) with ENOTEMPTY. Two related directories live under ~/.openclaw/plugin-runtime-deps/:

  • openclaw-2026.4.24-02f98c7ef353/ — the expected versioned dir
  • openclaw-unknown-2018ccba5afc/ — a shadow dir with unknown instead of a version. This appears to come from a version-detection fallback during install, and once it exists, every subsequent boot stages new plugin content into it but cannot complete because the destination tree already exists.

Trashing the entire ~/.openclaw/plugin-runtime-deps/ directory and restarting the gateway recreates the same broken pair immediately on first boot — so this isn't stale state from a prior install. The install logic itself produces the broken state.

Environment

  • openclaw: 2026.4.24
  • node: v25.9.0 (also reproduced under v24.14.0 nvm)
  • npm: 11.12.1
  • macOS: 26.3.1
  • Bound: loopback ws://127.0.0.1:18789

Reproduction

  1. With openclaw installed and gateway running, observe ~/.openclaw/plugin-runtime-deps/ contains a versioned dir (openclaw-<version>-<hash>) AND a shadow openclaw-unknown-<hash> dir.
  2. trash ~/.openclaw/plugin-runtime-deps
  3. launchctl kickstart -k gui/$UID/ai.openclaw.gateway
  4. After restart, ls ~/.openclaw/plugin-runtime-deps/ shows both dirs again.
  5. openclaw status reports [plugins] telegram failed during register with ENOTEMPTY.

Concrete error log lines

From ~/.openclaw/logs/gateway.err.log, two distinct ENOTEMPTY shapes seen back-to-back across two consecutive gateway restarts (timestamps within the same incident, log lines abbreviated for readability):

[plugins] telegram failed during register from
  /…/node_modules/openclaw/dist/extensions/telegram/index.js:
  Error: ENOTEMPTY, Directory not empty:
    /Users/<user>/.openclaw/plugin-runtime-deps/openclaw-unknown-2018ccba5afc/dist/extensions/node_modules/openclaw/plugin-sdk
    '/Users/<user>/.openclaw/plugin-runtime-deps/openclaw-unknown-2018ccba5afc/dist/extensions/node_modules/openclaw/plugin-sdk'
[plugins] telegram failed during register from
  /…/node_modules/openclaw/dist/extensions/telegram/index.js:
  Error: ENOTEMPTY: directory not empty, rename
    '/Users/<user>/.openclaw/plugin-runtime-deps/openclaw-unknown-2018ccba5afc/dist/extensions/.plugin-telegram-pgHesQ/plugin'
    '/Users/<user>/.openclaw/plugin-runtime-deps/openclaw-unknown-2018ccba5afc/dist/extensions/telegram'

The .plugin-telegram-<random> directory naming suggests a "stage to temp dir then atomic rename" pattern. The atomic rename is failing because the destination (extensions/telegram) already exists from a prior boot's partial install — and the rename target itself is a directory, so fs.renameSync cannot replace it.

Earlier on the same boot, the node_modules/openclaw/plugin-sdk ENOTEMPTY suggests the same atomic-replace pattern is applied to the bundled plugin-sdk SDK at a different stage.

Other bundled channels error similarly (visible in openclaw status output): bluebubbles, discord, googlechat, imessage, irc, msteams, nextcloud-talk, nostr, synology-chat, twitch, whatsapp. They all hit the same ENOTEMPTY on extensions/node_modules/openclaw/plugin-sdk in both the versioned and unknown- shadow dirs.

Likely root cause

Two suspected issues working together:

  1. Version detection occasionally returns unknown, which makes the install pick a different runtime-deps directory name (openclaw-unknown-<hash>) instead of openclaw-<version>-<hash>. This shadow dir then accumulates state independently from the versioned one.

  2. Plugin extraction is not idempotent. The "stage to temp dir, then rename to final location" pattern doesn't account for the final-location dir already existing. On a clean install this works; on subsequent installs, renameSync of dir → dir hits ENOTEMPTY. The extraction logic should either:

    • rm -rf (or platform-equivalent) the destination dir before rename, OR
    • skip the install if a valid version is already present, OR
    • use a content-addressed install path so successive installs don't collide.

The plugin-sdk ENOTEMPTY at the node_modules/openclaw/plugin-sdk path is a related but separate manifestation of the same non-idempotent extraction.

Impact

  • The bundled Telegram plugin fails to register entirely; any code path using openclaw gateway call chat.send or the openclaw-mediated Telegram delivery fails.
  • Workaround: applications that need Telegram delivery can bypass the plugin and curl https://api.telegram.org/bot<token>/sendMessage directly. We've been doing this in our integration successfully.
  • The gateway itself otherwise functions; openclaw status still produces output, just with the plugin errors prepended.

Suggested next steps

  • Reproduce locally with the steps above and verify the openclaw-unknown-* shadow dir is created on every gateway boot.
  • Make plugin extraction idempotent (delete destination before rename, or use a content-hashed final path).
  • Surface the version-detection failure that produces unknown rather than silently producing a parallel install dir.

Happy to capture more diagnostics on request — sanitized log files, gateway start traces, or a minimal repro on a different machine.

extent analysis

TL;DR

The most likely fix is to make the plugin extraction idempotent by deleting the destination directory before renaming or using a content-hashed final path.

Guidance

  • Verify the openclaw-unknown-* shadow directory is created on every gateway boot by reproducing the issue locally with the provided steps.
  • To make plugin extraction idempotent, consider implementing one of the following:
    • Delete the destination directory before renaming using rm -rf or a platform-equivalent command.
    • Skip the install if a valid version is already present.
    • Use a content-addressed install path to prevent successive installs from colliding.
  • Investigate and surface the version-detection failure that produces unknown instead of silently producing a parallel install directory.

Example

No code snippet is provided as the issue does not explicitly mention a specific code block that needs modification. However, an example of making the plugin extraction idempotent could involve modifying the installation script to delete the destination directory before renaming:

const fs = require('fs');
const path = require('path');

// Assuming 'tempDir' is the temporary directory and 'finalDir' is the final destination
fs.rmSync(finalDir, { recursive: true, force: true });
fs.renameSync(tempDir, finalDir);

Note that this is a hypothetical example and may not directly apply to the actual codebase.

Notes

The provided guidance is based on the information given in the issue and may not be exhaustive. Further investigation and debugging may be required to fully resolve the issue.

Recommendation

Apply a workaround by making the plugin extraction idempotent, as this addresses the root cause of the issue and prevents the ENOTEMPTY error. This approach allows for a more robust and reliable installation process.

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

openclaw - 💡(How to fix) Fix Plugin register fails with ENOTEMPTY in openclaw-unknown-* shadow runtime-deps dir on every gateway boot [2 comments, 3 participants]