openclaw - ✅(Solved) Fix TUI fails to start: "Cannot read properties of undefined (reading 't')" in slack contract-api legacyConfigRules getter [2 pull requests, 1 comments, 2 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#63360Fetched 2026-04-09 07:54:47
View on GitHub
Comments
1
Participants
2
Timeline
8
Reactions
0
Author
Participants
Timeline (top)
cross-referenced ×2referenced ×2closed ×1commented ×1

openclaw tui fails at startup with a TypeError originating from the bundled Slack plugin's contract-api.js. Config loading aborts before the TUI ever renders.

Error Message

Failed to read config at /home/<user>/.openclaw/openclaw.json TypeError: Cannot read properties of undefined (reading 't')
    at Object.get [as legacyConfigRules] (.../openclaw/dist/extensions/slack/contract-api.js:1:647)
    at resolvePluginDoctorContracts (.../openclaw/dist/config-DMMR1XE_.js:220:52)
    at listPluginDoctorLegacyConfigRules (.../openclaw/dist/config-DMMR1XE_.js:233:9)
    at resolveLegacyConfigForRead (.../openclaw/dist/config-DMMR1XE_.js:19138:82)
    at Object.loadConfig (.../openclaw/dist/config-DMMR1XE_.js:19203:29)
    at loadPinnedRuntimeConfig (.../openclaw/dist/runtime-snapshot-BVfF9E0s.js:42:17)
    at loadConfig (.../openclaw/dist/config-DMMR1XE_.js:19669:9)
    at primeConfiguredContextWindows (.../openclaw/dist/context-CIaFOK75.js:119:39)
    at ensureContextWindowCacheLoaded (.../openclaw/dist/context-CIaFOK75.js:137:15)

Root Cause

Root cause (diagnosis)

Fix Action

Workaround

Replacing dist/extensions/slack/contract-api.js with a stub that exports legacyConfigRules = [] lets the TUI start.

PR fix notes

PR #63363: fix(slack): move outbound payload test harness off contract-api entrypoint

Description (problem / solution / changelog)

Summary

  • extensions/slack/contract-api.ts re-exported createSlackOutboundPayloadHarness, which transitively imports vi from vitest plus other test-only helpers. That pulled the vitest harness into the production plugin-contract bundle.
  • At runtime, resolvePluginDoctorContracts loads dist/extensions/slack/contract-api.js via jiti to read legacyConfigRules. The nested relative ESM imports don't resolve under jiti, so the live binding for legacyConfigRules ends up undefined, and the compiled getter throws TypeError: Cannot read properties of undefined (reading 't'). Config loading aborts for every command, including openclaw tui.
  • Moves createSlackOutboundPayloadHarness to extensions/slack/test-api.ts (matching how matrix and other plugins keep test helpers out of the contract entrypoint) and updates the single in-tree consumer (test/helpers/channels/outbound-payload-contract.ts).

Fixes #63360

Test plan

  • Build succeeds
  • outbound-payload-contract tests still pass
  • After publish, openclaw tui starts cleanly with a config containing a channels.slack block
  • dist/extensions/slack/contract-api.js no longer imports vitest / testing-* chunks

Changed files

  • extensions/slack/contract-api.ts (modified, +0/-1)
  • extensions/slack/test-api.ts (modified, +1/-0)
  • test/helpers/channels/outbound-payload-contract.ts (modified, +1/-1)

PR #63364: fix(slack): move outbound payload test harness off contract-api entrypoint

Description (problem / solution / changelog)

Resubmitting #63363 (auto-closed by the PR-cap bot).

Summary

  • extensions/slack/contract-api.ts re-exported createSlackOutboundPayloadHarness, which transitively imports vi from vitest plus other test-only helpers. That pulled the vitest harness into the production plugin-contract bundle.
  • At runtime, resolvePluginDoctorContracts loads dist/extensions/slack/contract-api.js via jiti to read legacyConfigRules. The nested relative ESM imports don't resolve under jiti, so the live binding for legacyConfigRules ends up undefined, and the compiled getter throws TypeError: Cannot read properties of undefined (reading 't'). Config loading aborts for every command, including openclaw tui.
  • Moves createSlackOutboundPayloadHarness to extensions/slack/test-api.ts (matching how matrix and other plugins keep test helpers out of the contract entrypoint) and updates the single in-tree consumer.

Fixes #63360

Reproduction backtrace

Running openclaw tui against any config that exercises the slack plugin contract:

Failed to read config at /home/<user>/.openclaw/openclaw.json TypeError: Cannot read properties of undefined (reading 't')
    at Object.get [as legacyConfigRules] (.../openclaw/dist/extensions/slack/contract-api.js:1:647)
    at resolvePluginDoctorContracts (.../openclaw/dist/config-DMMR1XE_.js:220:52)
    at listPluginDoctorLegacyConfigRules (.../openclaw/dist/config-DMMR1XE_.js:233:9)
    at resolveLegacyConfigForRead (.../openclaw/dist/config-DMMR1XE_.js:19138:82)
    at Object.loadConfig (.../openclaw/dist/config-DMMR1XE_.js:19203:29)
    at loadPinnedRuntimeConfig (.../openclaw/dist/runtime-snapshot-BVfF9E0s.js:42:17)
    at loadConfig (.../openclaw/dist/config-DMMR1XE_.js:19669:9)
    at primeConfiguredContextWindows (.../openclaw/dist/context-CIaFOK75.js:119:39)
    at ensureContextWindowCacheLoaded (.../openclaw/dist/context-CIaFOK75.js:137:15)

The literal 't' is the minified re-export name for legacyConfigRules in doctor-contract-Byp5_Sbd.js — when jiti fails to resolve that nested chunk, the live binding is undefined and the compiled getter blows up.

Test plan

  • Build succeeds
  • outbound-payload-contract tests still pass
  • After publish, openclaw tui starts cleanly with a config containing a channels.slack block
  • dist/extensions/slack/contract-api.js no longer imports vitest / testing-* chunks

Changed files

  • extensions/slack/contract-api.ts (modified, +0/-1)
  • extensions/slack/src/outbound-payload.test.ts (modified, +1/-1)
  • extensions/slack/test-api.ts (modified, +1/-0)
  • test/helpers/channels/outbound-payload-contract.ts (modified, +1/-1)

Code Example

Failed to read config at /home/<user>/.openclaw/openclaw.json TypeError: Cannot read properties of undefined (reading 't')
    at Object.get [as legacyConfigRules] (.../openclaw/dist/extensions/slack/contract-api.js:1:647)
    at resolvePluginDoctorContracts (.../openclaw/dist/config-DMMR1XE_.js:220:52)
    at listPluginDoctorLegacyConfigRules (.../openclaw/dist/config-DMMR1XE_.js:233:9)
    at resolveLegacyConfigForRead (.../openclaw/dist/config-DMMR1XE_.js:19138:82)
    at Object.loadConfig (.../openclaw/dist/config-DMMR1XE_.js:19203:29)
    at loadPinnedRuntimeConfig (.../openclaw/dist/runtime-snapshot-BVfF9E0s.js:42:17)
    at loadConfig (.../openclaw/dist/config-DMMR1XE_.js:19669:9)
    at primeConfiguredContextWindows (.../openclaw/dist/context-CIaFOK75.js:119:39)
    at ensureContextWindowCacheLoaded (.../openclaw/dist/context-CIaFOK75.js:137:15)

---

import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "../../doctor-contract-Byp5_Sbd.js";

---

mod = getJiti(contractSource)(contractSource);
...
const rules = coerceLegacyConfigRules(mod.default?.legacyConfigRules ?? mod.legacyConfigRules);
RAW_BUFFERClick to expand / collapse

Summary

openclaw tui fails at startup with a TypeError originating from the bundled Slack plugin's contract-api.js. Config loading aborts before the TUI ever renders.

Version

OpenClaw 2026.4.8 (9ece252), installed via npm -g install openclaw. Node ESM, Linux.

Stack trace

Failed to read config at /home/<user>/.openclaw/openclaw.json TypeError: Cannot read properties of undefined (reading 't')
    at Object.get [as legacyConfigRules] (.../openclaw/dist/extensions/slack/contract-api.js:1:647)
    at resolvePluginDoctorContracts (.../openclaw/dist/config-DMMR1XE_.js:220:52)
    at listPluginDoctorLegacyConfigRules (.../openclaw/dist/config-DMMR1XE_.js:233:9)
    at resolveLegacyConfigForRead (.../openclaw/dist/config-DMMR1XE_.js:19138:82)
    at Object.loadConfig (.../openclaw/dist/config-DMMR1XE_.js:19203:29)
    at loadPinnedRuntimeConfig (.../openclaw/dist/runtime-snapshot-BVfF9E0s.js:42:17)
    at loadConfig (.../openclaw/dist/config-DMMR1XE_.js:19669:9)
    at primeConfiguredContextWindows (.../openclaw/dist/context-CIaFOK75.js:119:39)
    at ensureContextWindowCacheLoaded (.../openclaw/dist/context-CIaFOK75.js:137:15)

Root cause (diagnosis)

dist/extensions/slack/contract-api.js re-exports legacyConfigRules from a nested ESM chunk:

import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "../../doctor-contract-Byp5_Sbd.js";

resolvePluginDoctorContracts (config-DMMR1XE_.js:220) loads this file via jiti:

mod = getJiti(contractSource)(contractSource);
...
const rules = coerceLegacyConfigRules(mod.default?.legacyConfigRules ?? mod.legacyConfigRules);

Under jiti, the nested ESM import resolves to undefined, so the compiled live-binding getter ends up doing undefined.t and throws "Cannot read properties of undefined (reading 't')". The literal 't' is the minified re-export name from doctor-contract-Byp5_Sbd.js.

Loading the same module directly with native import() works fine — Object.keys returns ['n','t'] — so the file itself is valid; the failure is specific to jiti's handling of these nested relative ESM chunks.

Additionally, the same contract-api.js imports test-only helpers (vi, primeChannelOutboundSendMock, createSlackOutboundPayloadHarness) from test.p_J6dB8a-QET2Xqom.js / testing-DtIZqkvR.js. These look like vitest harness code that shouldn't be shipped in the production plugin contract entrypoint, and they likely contribute to jiti's resolution failure.

Reproduction

  1. npm -g install [email protected]
  2. openclaw tui

Crashes immediately, regardless of what's in ~/.openclaw/openclaw.json (removing the channels.slack block does not help — the plugin contract is loaded unconditionally).

Suggested fixes

  • Don't bundle test-harness imports (vi, primeChannelOutboundSendMock, createSlackOutboundPayloadHarness) into the published extensions/slack/contract-api.js. Move them to a separate test entrypoint.
  • Either avoid jiti for loading plugin contract modules (use native import() since the files are ESM), or ensure plugin contract entrypoints are self-contained without nested relative ESM re-exports.
  • Defensive: in resolvePluginDoctorContracts, wrap the mod.legacyConfigRules access in try/catch so a single broken plugin contract doesn't take down config loading entirely.

Workaround

Replacing dist/extensions/slack/contract-api.js with a stub that exports legacyConfigRules = [] lets the TUI start.

extent analysis

TL;DR

The most likely fix is to modify the contract-api.js file to avoid bundling test-harness imports and to use native import() instead of jiti for loading plugin contract modules.

Guidance

  • Remove test-only helpers (vi, primeChannelOutboundSendMock, createSlackOutboundPayloadHarness) from contract-api.js to prevent jiti resolution failure.
  • Consider using native import() instead of jiti for loading plugin contract modules to avoid issues with nested relative ESM re-exports.
  • Wrap the mod.legacyConfigRules access in try/catch to prevent a single broken plugin contract from taking down config loading entirely.
  • As a temporary workaround, replacing dist/extensions/slack/contract-api.js with a stub that exports legacyConfigRules = [] can allow the TUI to start.

Example

No code snippet is provided as the issue is related to the build and loading process of the modules.

Notes

The issue seems to be specific to the jiti handling of nested relative ESM chunks. The provided workaround can help to start the TUI, but a proper fix would require modifying the contract-api.js file and the loading process.

Recommendation

Apply the suggested fixes to modify the contract-api.js file and the loading process to avoid jiti resolution failure and ensure proper loading of plugin contract modules. This approach is more reliable and maintainable than relying on workarounds.

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