Bug
Since 2026.4.7, all CLI commands crash with:
TypeError: Cannot read properties of undefined (reading 't')
at Object.get [as legacyConfigRules] (.../extensions/slack/contract-api.js:1:647)
at resolvePluginDoctorContracts (.../config-DMMR1XE_.js:220:52)
This breaks openclaw cron list, openclaw cron add, openclaw message send, openclaw health, and all other CLI operations. The gateway process is unaffected (it uses native ESM imports).
Reproduced on 2026.4.7 and 2026.4.8. Not present in 2026.4.2.
Root cause
Two missing error boundaries in the plugin contract loading path:
1. resolvePluginDoctorContracts (config loader)
The Slack plugin's contract-api.js uses ESM imports. When loaded by jiti (CJS-compat), the imports become lazy getters on the module object. These getters throw when the underlying ESM resolution fails in the jiti context.
The current code wraps only the getJiti()() call in try/catch, but the property access on the returned module is outside the catch:
// Current (config-DMMR1XE_.js:214-221)
let mod;
try {
mod = getJiti(contractSource)(contractSource);
} catch {
continue; // catches load errors
}
// These lines throw when jiti lazy getters fail:
const rules = coerceLegacyConfigRules(mod.default?.legacyConfigRules ?? mod.legacyConfigRules);
const normalizeCompatibilityConfig = ...
2. getBundledChannelSetupPlugin (bundled plugin loader)
The Telegram plugin's setup-entry.js references ./src/channel.setup.js which doesn't exist in the built package. The load call uses try/finally without a catch:
// Current (bundled-BUZYiQLp.js:256-262)
try {
const plugin = entry.loadSetupPlugin();
state.setupPluginsById.set(id, plugin);
return plugin;
} finally {
setupPluginLoadInProgressIds.delete(id);
}
Fix
Fix 1: Extend try/catch to cover lazy getter access
let mod;
let rules;
let normalizeCompatibilityConfig;
try {
mod = getJiti(contractSource)(contractSource);
rules = coerceLegacyConfigRules(mod.default?.legacyConfigRules ?? mod.legacyConfigRules);
normalizeCompatibilityConfig = coerceNormalizeCompatibilityConfig(
mod.normalizeCompatibilityConfig ?? mod.default?.normalizeCompatibilityConfig
);
} catch {
continue;
}
Fix 2: Add catch block for setup plugin loading
try {
const plugin = entry.loadSetupPlugin();
state.setupPluginsById.set(id, plugin);
return plugin;
} catch {
return;
} finally {
setupPluginLoadInProgressIds.delete(id);
}
Environment
- OpenClaw 2026.4.7 and 2026.4.8
- Node.js 25.8.0
- macOS (darwin)
- Gateway runs as LaunchAgent on loopback
Bug
Since 2026.4.7, all CLI commands crash with:
This breaks
openclaw cron list,openclaw cron add,openclaw message send,openclaw health, and all other CLI operations. The gateway process is unaffected (it uses native ESM imports).Reproduced on 2026.4.7 and 2026.4.8. Not present in 2026.4.2.
Root cause
Two missing error boundaries in the plugin contract loading path:
1.
resolvePluginDoctorContracts(config loader)The Slack plugin's
contract-api.jsuses ESM imports. When loaded by jiti (CJS-compat), the imports become lazy getters on the module object. These getters throw when the underlying ESM resolution fails in the jiti context.The current code wraps only the
getJiti()()call in try/catch, but the property access on the returned module is outside the catch:2.
getBundledChannelSetupPlugin(bundled plugin loader)The Telegram plugin's
setup-entry.jsreferences./src/channel.setup.jswhich doesn't exist in the built package. The load call usestry/finallywithout acatch:Fix
Fix 1: Extend try/catch to cover lazy getter access
Fix 2: Add catch block for setup plugin loading
Environment