Windows Control UI Update Leaves External Discord Plugin in Stale/Broken Install State
On Windows, a Control UI update can leave external npm channel plugins in a broken state where managed repair commands fail with 'Cannot read properties of undefined (reading spec)', requiring manual npm surgery to restore plugin functionality.
π Symptoms
Primary Error Manifestations
On Windows 11, after a Control UI update from OpenClaw 2026.5.2 to 2026.5.7, the external Discord channel plugin enters a broken state characterized by the following sequential errors:
1. Control UI Update Failure
2026-05-10T16:21:14.597+09:00 update.run completed actor=openclaw-control-ui ... restartReason=update.run status=error
2026-05-10T16:21:14.600+09:00 β res β update.run 97819ms ...
2026-05-10T16:25:00.469+09:00 update.run completed actor=openclaw-control-ui ... restartReason=update.run status=error
2026-05-10T16:25:00.472+09:00 β res β update.run 212ms ...The Gateway service continues running, but the Discord plugin is now broken.
2. TypeScript Source Path Detection
The system discovers the plugin from uncompiled source paths instead of compiled runtime output:
[plugins] plugins.allow is empty; discovered non-bundled plugins may auto-load:
discord (...\.openclaw\npm\node_modules\@openclaw\discord\index.ts)
Error: Unable to resolve bundled plugin public surface speech-core/runtime-api.js3. Plugin Install Blocked by Existing Directory
19:54:34 Downloading @openclaw/discordβ¦
19:54:35 Extracting ... openclaw-discord-2026.5.7.tgzβ¦
19:54:37 ERROR plugin already exists:
C:\Users\...\node_modules\@openclaw\discord
(delete it first)
Use `openclaw plugins update ` to upgrade the tracked plugin,
or rerun install with `--force` to replace it.
19:54:52 ERROR Plugin not found: discord 4. Managed Plugin Repair Commands Fail with Arborist Error
C:\> openclaw plugins update discord
β npm install failed: Cannot read properties of undefined (reading 'spec')
C:\> openclaw plugins install @openclaw/discord --force --pin
β npm install failed: Cannot read properties of undefined (reading 'spec')5. Plugin Metadata Drift
After manual recovery, the plugin index shows version drift:
Plugin index includes unpinned npm specs
Plugin index records drift from installed package versions
- discord (recorded 2026.5.2, installed 2026.5.7)6. Compiled Runtime Output Validation Failure
Config warnings:
- plugins.entries.discord: plugin discord: installed plugin package requires compiled runtime output
for TypeScript entry setup-entry.ts: expected ./dist/setup-entry.js, ./dist/setup-entry.mjs,
./dist/setup-entry.cjs, setup
[plugins] installed plugin package requires compiled runtime output for TypeScript entry index.ts:
expected ./dist/index.js, ./dist/index.mjs, ./dist/index.cjs, index.js, index.mjs, index.cjs
(plugin=discord, source=$OPENCLAW_STATE_DIR\npm\...)Environment Context
- Operating System: Windows 11 / Windows_NT 10.0.26200 x64
- Install Method: npm global on Windows
- Gateway Service: Windows Scheduled Task installed by OpenClaw 2026.5.2
- Plugin Location:
%USERPROFILE%.openclaw\npm\node_modules@openclaw\discord
π§ Root Cause
Primary Failure Sequence
The bug manifests through a cascading failure across multiple OpenClaw subsystems:
1. Control UI Update Flow Incomplete Plugin Sync
When the Control UI update flow executes, it performs the following operations:
- Downloads the OpenClaw 2026.5.7 package
- Updates the npm global installation
- Triggers a Gateway service restart with
restartReason=update.run
However, if external npm channel plugins are present in %USERPROFILE%.openclaw\npm, the update flow does not:
- Synchronize external plugin package versions
- Validate plugin directory integrity after restart
- Clean stale plugin metadata before Gateway reinitialization
This leaves the external plugin directory in a partially-updated state where:
- The old 2026.5.2 plugin package remains in
node_modules - Plugin metadata references may point to missing or stale entries
- Compiled runtime artifacts (
dist/*.js) are either missing or reference incompatible paths
2. TypeScript Entry Point Detection Without Compiled Output
The plugin discovery system in 2026.5.7 includes enhanced TypeScript entry point detection (referenced in v2026.5.7 release notes fixing #77779 via #77799). When a plugin directory exists but contains:
- Only
index.tssource files - Missing
dist/setup-entry.jscompiled artifacts - Stale metadata referencing version 2026.5.2
The discovery logic finds the .ts source path but cannot load it as a valid plugin, causing the Plugin not found: discord error.
3. npm Arborist spec Undefined Error
The Cannot read properties of undefined (reading ‘spec’) error originates in the npm arborist integration within OpenClaw’s plugin manager. This occurs when:
- Stale Plugin Record: The plugin index contains a record for
discordwith version2026.5.2 - Missing arborist node: The arborist's internal tree does not have a corresponding node for the external plugin path
- Attempted repair operation: When
openclaw plugins updateoropenclaw plugins install --forceruns, it attempts to accessarboristNode.specon a node that does not exist in the arborist tree
The arborist tree for %USERPROFILE%.openclaw\npm was populated for the original 2026.5.2 install but never updated during the failed Control UI update. The plugin record exists in OpenClaw’s metadata but not in the current npm tree state.
4. Directory Pre-existence Blocks Reinstall
The npm install logic checks if node_modules@openclaw\discord exists before attempting extraction. Because the directory exists (from 2026.5.2), the reinstall path is blocked with:
ERROR plugin already exists: ...\node_modules\@openclaw\discord
(delete it first)This prevents the normal recovery path of downloading and extracting the 2026.5.7 package over the stale 2026.5.2 installation.
5. Service Metadata Drift
The Gateway service was installed by OpenClaw 2026.5.2. After the Control UI update to 2026.5.7:
- The CLI reports version 2026.5.7
- The scheduled task service definition references the old 2026.5.2 binaries
- A service repair attempt fails with
schtasks create failed: Access is denied
This service drift compounds the recovery complexity but does not directly cause the plugin failure.
Architectural Gaps
| Gap | Location | Consequence |
|---|---|---|
| External plugin sync missing in update flow | Control UI β Gateway update handler | Stale external plugins after update |
| arborist tree not refreshed after plugin record drift | PluginManager.ts | Cannot read properties of undefined (reading ‘spec’) |
| No validation of compiled runtime output during discovery | PluginDiscovery.ts | TypeScript sources detected but not usable |
| Pre-existence check prevents overwrite without force flag | NpmPluginInstaller.ts | Blocked reinstall even with –force |
| Service repair fails on permission error | WindowsServiceManager.ts | Service metadata drift persists |
π οΈ Step-by-Step Fix
Recovery Options
There are two recovery paths: the managed repair (if available) and the manual npm workaround.
Option A: Manual npm Install Workaround (Verified Working)
This is the only fully reliable recovery path given the current bug state.
Step 1: Identify the OpenClaw npm Root Directory
echo %USERPROFILE%\.openclaw\npmExpected output:
C:\Users\<username>\.openclaw\npmStep 2: Navigate to the npm Root and Remove the Stale Plugin Directory
cd /d %USERPROFILE%\.openclaw\npm
rmdir /s /q node_modules\@openclaw\discordWarning: This removes the broken plugin directory. Ensure the Gateway service is stopped or will be restarted after recovery.
Step 3: Perform Direct npm Install
npm install @openclaw/discord@2026.5.7 --omit=dev --omit=peer --legacy-peer-deps --ignore-scripts --no-audit --no-fund --save-exactExpected output:
added 18 packages in 5s
DIST_INDEX_OKStep 4: Restart the Gateway Service
net stop OpenClawGateway
net start OpenClawGatewayOr via OpenClaw CLI:
openclaw gateway restartStep 5: Verify Plugin Loading
Check the Gateway logs for successful Discord plugin initialization:
openclaw logs --tail 50 | findstr /i discordExpected output should show:
Discord default: enabled, configured, running, connected
bot:@clawed-bot-home
works, audit okOption B: Clear Plugin Record and Reinstall (If Available)
This path may also fail with the arborist error until the bug is fixed.
Step 1: Remove the Plugin Record
openclaw plugins remove discordStep 2: Clear the Plugin Directory
rmdir /s /q %USERPROFILE%\.openclaw\npm\node_modules\@openclaw\discordStep 3: Reinstall the Plugin
openclaw plugins install @openclaw/discord --pinOption C: Preventive Fix for Future Updates (CLI-Level)
To prevent this issue during future updates, run plugin sync before initiating a Control UI update:
Step 1: Update All External Plugins Before Control UI Update
openclaw plugins update --allStep 2: Verify Plugin Health
openclaw plugins doctorStep 3: Proceed with Control UI Update
After plugins are synchronized, the Control UI update should complete without leaving stale plugin state.
Before/After Configuration Comparison
Before (Broken State After Update)
# %USERPROFILE%\.openclaw\config\plugins.json
{
"entries": {
"discord": {
"id": "discord",
"version": "2026.5.2",
"source": "%USERPROFILE%\\.openclaw\\npm\\node_modules\\@openclaw\\discord",
"type": "external",
"pinned": false
}
}
}
# Plugin directory contents (incomplete):
%USERPROFILE%\.openclaw\npm\node_modules\@openclaw\discord\
index.ts β Source only, no compiled output
setup-entry.ts
package.json β References version 2026.5.2
# Missing: dist/setup-entry.js, dist/index.jsAfter (Recovered State)
# %USERPROFILE%\.openclaw\config\plugins.json (after manual sync)
{
"entries": {
"discord": {
"id": "discord",
"version": "2026.5.7",
"source": "%USERPROFILE%\\.openclaw\\npm\\node_modules\\@openclaw\\discord",
"type": "external",
"pinned": true
}
}
}
# Plugin directory contents (complete):
%USERPROFILE%\.openclaw\npm\node_modules\@openclaw\discord\
index.ts β Source (OK)
setup-entry.ts β Source (OK)
package.json β References version 2026.5.7
dist/
index.js β Compiled runtime output present
setup-entry.js
node_modules/ β Plugin dependenciesπ§ͺ Verification
Verification Checklist
Execute these commands in sequence to confirm complete recovery:
1. Verify OpenClaw Version
openclaw --versionExpected output:
OpenClaw 2026.5.7 (eeef486)2. Verify Plugin Status
openclaw plugins listExpected output (partial):
βββββββββββ¬ββββββββββββββββββββββ¬βββββββββββ¬βββββββββββββ
β Plugin β Version β Type β Status β
βββββββββββΌββββββββββββββββββββββΌβββββββββββΌβββββββββββββ€
β discord β 2026.5.7 β external β enabled β
β browser β (bundled) β internal β enabled β
β ... β ... β ... β ... β
βββββββββββ΄ββββββββββββββββββββββ΄βββββββββββ΄βββββββββββββ3. Verify Plugin Directory Integrity
dir /b %USERPROFILE%\.openclaw\npm\node_modules\@openclaw\discord\dist\Expected output should include:
index.js
setup-entry.js4. Verify Plugin Health
openclaw plugins doctorExpected output:
β discord: installed plugin package has compiled runtime output
β discord: plugin metadata matches installed version
β discord: no version drift detected
Plugin health check: PASSED (1/1 external plugins healthy)5. Verify Gateway Plugin Loading
openclaw logs --tail 100 | findstr /i "discord\|plugins loaded"Expected output:
[plugins] Loading plugin: discord
Discord default: enabled, configured, running, connected
bot:@clawed-bot-home
http server listening (8 plugins: browser, device-pair, discord, ...)6. Verify No Compiled Runtime Warnings
openclaw logs --tail 100 | findstr /i "compiled runtime output\|TypeScript entry"Expected output: No matches (no warnings about missing compiled runtime output).
7. Verify Plugin Index Consistency
openclaw plugins auditExpected output:
Plugin index includes pinned npm specs
Plugin index records match installed package versions
- discord (recorded 2026.5.7, installed 2026.5.7)
Plugin audit: PASSED8. Verify Gateway Service Metadata (Windows)
schtasks /query /tn "OpenClawGateway" /fo LISTExpected output should reference the current 2026.5.7 installation path.
9. Exit Codes Reference
| Command | Success Exit Code | Failure Exit Code |
|---|---|---|
openclaw plugins list | 0 | 1 |
openclaw plugins doctor | 0 | 1 |
openclaw plugins audit | 0 | 1 |
openclaw gateway status | 0 | 1 |
β οΈ Common Pitfalls
Environment-Specific Traps
Windows-Specific Issues
- PowerShell vs CMD Path Resolution
When using PowerShell, environment variables use different syntax:
# CMD syntax echo %USERPROFILE%\.openclaw\npmPowerShell syntax
echo $env:USERPROFILE.openclaw\npm
Mixing these syntaxes causes
directory not founderrors. - Long Path Handling
Windows has a default 260-character path limit. Deep npm dependency trees can exceed this:
%USERPROFILE%\.openclaw\npm\node_modules\@openclaw\discord\node_modules\@some-org\some-deep-dependency\...Enable long paths with:
New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" -Name "LongPathsEnabled" -Value 1 -PropertyType DWORD -Force - Antivirus/Folder Permission Interference
Windows Defender or corporate AV may hold file handles on npm directories, causing:
EPERM: operation not permitted, unlink '...\node_modules\@openclaw\discord'Close all programs accessing the directory and retry, or add exclusions.
- schtasks Access Denied
Gateway service repair requires administrator privileges:
Gateway repair failed: Error: schtasks create failed: Access is denied.Run Command Prompt or PowerShell as Administrator to repair service metadata.
npm-Specific Pitfalls
- Cache Contamination
Stale npm cache entries can cause package verification failures:
npm cache clean --force npm install @openclaw/discord@2026.5.7 ... - Global vs Local npm Conflict
If OpenClaw was installed globally but plugins are in a local directory:
npm root -g # Should match %USERPROFILE%\.openclaw\npm # If mismatch, plugins are not found by OpenClaw - --omit=dev Removes Required Runtime Dependencies
Some plugins may have runtime dependencies incorrectly listed as devDependencies. Verify after install:
cd %USERPROFILE%\.openclaw\npm npm ls @openclaw/discord
OpenClaw-Specific Pitfalls
- Gateway Must Restart After Manual npm Surgery
OpenClaw caches plugin metadata in memory. Changes to
node_modulesare not detected without restart:openclaw gateway restart - Plugin Record Drift Persists After Runtime Recovery
Even after
npm installsucceeds, the plugin index may retain old metadata:openclaw plugins update discord # Refreshes the record - Bundled vs External Plugin Conflict
If a plugin exists both as bundled and external, the external version may be shadowed:
openclaw plugins list # Check type column # external plugins should not have (bundled) indicator - Multiple OpenClaw Installations
Having both a per-user and system-wide installation can cause confusion:
where openclaw # Check for multiple entries npm ls -g openclaw # List all global installations
Edge Cases
- Interrupted Update: If Control UI update is interrupted mid-download, both old and new versions may be partially installed. Clean with
openclaw update --force. - Corrupted npm Lockfile: If
package-lock.jsonin the npm root is corrupted, delete it before reinstalling plugins. - Offline Installation: If the machine has no internet access,
npm installwill fail. Pre-download the.tgzarchive and install from file. - Concurrent Gateway Access: If multiple Gateway instances are running, plugin files may be locked. Stop all instances before manual surgery.
π Related Errors
Directly Related Errors
Cannot read properties of undefined (reading 'spec')Component: npm arborist integration in PluginManager
Trigger: Plugin record exists but arborist tree node does not
Reference: This issue
ERROR plugin already exists: ...\node_modules\@openclaw\discordComponent: NpmPluginInstaller
Trigger: Plugin directory pre-exists during install attempt
Reference: This issue
Plugin not found: discordComponent: PluginDiscovery
Trigger: Plugin directory exists but contains no valid entry point
Reference: This issue
installed plugin package requires compiled runtime outputComponent: PluginDiscovery TypeScript validation
Trigger: Plugin package contains
.tssources withoutdist/outputReference: This issue; related to #77799 fix in v2026.5.7
schtasks create failed: Access is deniedComponent: WindowsServiceManager
Trigger: Insufficient permissions for scheduled task modification
Reference: Service metadata drift in this issue
update.run completed ... status=errorComponent: Control UI update handler
Trigger: Update flow fails to complete plugin synchronization
Reference: This issue
Historically Related Issues
- #77779 / #77799: Plugin/channel setup and TypeScript entry handling
v2026.5.7 release notes mention forward
setChannelRuntimefrom non-bundled external plugin setup entries. The enhanced TypeScript entry validation may be contributing to the detection of broken states that previously went unnoticed. - External plugin installation/update/doctor repair (appcast.xml for 2026.5.2)
The 2026.5.2 release specifically addressed external plugin lifecycle including stale configured installs, missing package payloads, npm-first cutover, and beta-channel plugin fallback.
- npm arborist integration failures
Community reports of
Cannot read properties of undefinederrors during plugin operations suggest the arborist tree synchronization is a known fragile path.
Known Affected Versions
- OpenClaw 2026.5.2 (initial state)
- OpenClaw 2026.5.7 (update target; contains regression in plugin sync)
- Future versions until fix is released
Recommended Upstream Fixes
| Priority | Fix Description | Affected Component |
|---|---|---|
| Critical | Refresh arborist tree before plugin update/install operations | PluginManager |
| Critical | Add external plugin sync step to Control UI update flow | UpdateHandler |
| High | Validate compiled runtime output before plugin record update | PluginDiscovery |
| High | Implement graceful degradation when plugin directory exists | NpmPluginInstaller |
| Medium | Add –repair flag to force complete plugin state reconciliation | CLI |