Skip to content

fix: resolve CHANNEL_IDS temporal dead zone on module init (#48832)#60061

Merged
BradGroux merged 1 commit intoopenclaw:mainfrom
BradGroux:bgod/fix-48832-channel-ids-init-order
Apr 3, 2026
Merged

fix: resolve CHANNEL_IDS temporal dead zone on module init (#48832)#60061
BradGroux merged 1 commit intoopenclaw:mainfrom
BradGroux:bgod/fix-48832-channel-ids-init-order

Conversation

@BradGroux
Copy link
Copy Markdown
Contributor

Problem

CHANNEL_IDS throws "is not iterable" on startup (Windows, also reproduced on Debian/Docker). This is a temporal dead zone (TDZ) error.

Root Cause

src/config/schema.ts and src/config/validation.ts imported CHANNEL_IDS from channels/registry.js, which re-exports from the leaf module channels/ids.js but also imports plugins/runtime.js and channels/chat-meta.js. When the bundler (tsdown/ESM) resolves this dependency graph, the re-exported CHANNEL_IDS binding can be undefined at the point where config modules evaluate — classic TDZ from circular or deep import chains.

Fix

Import CHANNEL_IDS directly from channels/ids.js (zero-dependency leaf module) and normalizeChatChannelId from channels/chat-meta.js instead of routing through the heavyweight channels/registry.js barrel.

Files changed: src/config/schema.ts, src/config/validation.ts

Fixes #48832

…aw#48832)

schema.ts and validation.ts imported CHANNEL_IDS from channels/registry.js,
which re-exports from channels/ids.js but also imports plugins/runtime.js.
When the bundler resolves this dependency graph, the re-exported CHANNEL_IDS
can be undefined at the point config/validation.ts evaluates (temporal dead
zone), causing 'CHANNEL_IDS is not iterable' on startup.

Fix: import CHANNEL_IDS directly from channels/ids.js (the leaf module with
zero heavy dependencies) and normalizeChatChannelId from channels/chat-meta.js.

Fixes openclaw#48832
Copilot AI review requested due to automatic review settings April 3, 2026 04:03
@openclaw-barnacle openclaw-barnacle bot added size: XS maintainer Maintainer-authored PR labels Apr 3, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 3, 2026

Greptile Summary

This PR fixes a temporal dead zone (TDZ) crash on startup (Windows and Debian/Docker) by redirecting two imports in src/config/schema.ts and src/config/validation.ts away from the heavy channels/registry.ts barrel — which transitively loads plugins/runtime.js — to the appropriate leaf modules:

  • CHANNEL_IDS now comes from channels/ids.ts (zero-dependency leaf, already the canonical source that registry.ts re-exports)
  • normalizeChatChannelId now comes from channels/chat-meta.ts (no plugins/runtime.js dependency), matching the original definition that registry.ts merely re-exported

Both import targets are the original definition sites, so runtime behavior is identical. The fix is minimal, targeted, and accurately described in the PR body.

Confidence Score: 5/5

Safe to merge — two-line targeted fix that routes imports to their original definition sites, eliminating the TDZ without any behavior change.

The change is minimal and provably correct: CHANNEL_IDS was already re-exported from ids.ts through registry.ts (registry.ts line 12), and normalizeChatChannelId was re-exported from chat-meta.ts through registry.ts (lines 7 and 63). Both new imports resolve to the exact same definitions, just without the intervening registry.ts barrel that loads plugins/runtime.js at module-init time. No logic is altered, no new dependencies are introduced, and chat-meta.ts itself only depends on static bundled metadata — not the plugin runtime — so the TDZ hazard is fully eliminated.

No files require special attention.

Reviews (1): Last reviewed commit: "fix: import CHANNEL_IDS from leaf module..." | Re-trigger Greptile

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates config initialization imports to avoid pulling CHANNEL_IDS through channels/registry.js, which can trigger circular-import/TDZ failures during bundled ESM module evaluation (notably on Windows startup).

Changes:

  • Switch CHANNEL_IDS imports in config modules to the leaf src/channels/ids.js.
  • Switch normalizeChatChannelId import in config validation to src/channels/chat-meta.js (instead of the channels/registry.js barrel).

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/config/validation.ts Adjusts channel-related imports to avoid the registry barrel during config validation init.
src/config/schema.ts Imports CHANNEL_IDS directly from the leaf ids module to avoid registry/runtime init ordering issues.
Comments suppressed due to low confidence (1)

src/config/validation.ts:8

  • Although this file no longer imports CHANNEL_IDS/normalizeChatChannelId from ../channels/registry.js, it still imports normalizePluginsConfig/resolveEffectivePluginActivationState from ../plugins/config-state.js (line 7+), and src/plugins/config-state.ts currently imports normalizeChatChannelId from ../channels/registry.js at module top-level. That means the channels/registry -> plugins/runtime dependency chain can still be pulled in during config validation module initialization, so the original TDZ/circular-init startup failure may persist. Consider updating src/plugins/config-state.ts (and any other early-init dependencies) to import normalizeChatChannelId from a non-runtime leaf (e.g. ../channels/chat-meta.js) or moving the normalization helper into a leaf module to fully break the cycle.
import path from "node:path";
import { resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../agents/agent-scope.js";
import { CHANNEL_IDS } from "../channels/ids.js";
import { normalizeChatChannelId } from "../channels/chat-meta.js";
import { withBundledPluginAllowlistCompat } from "../plugins/bundled-compat.js";
import { listBundledWebSearchPluginIds } from "../plugins/bundled-web-search-ids.js";
import {
  normalizePluginsConfig,

@BradGroux BradGroux self-assigned this Apr 3, 2026
@BradGroux BradGroux merged commit 0aa98a8 into openclaw:main Apr 3, 2026
47 of 48 checks passed
ngutman pushed a commit that referenced this pull request Apr 3, 2026
#60061)

schema.ts and validation.ts imported CHANNEL_IDS from channels/registry.js,
which re-exports from channels/ids.js but also imports plugins/runtime.js.
When the bundler resolves this dependency graph, the re-exported CHANNEL_IDS
can be undefined at the point config/validation.ts evaluates (temporal dead
zone), causing 'CHANNEL_IDS is not iterable' on startup.

Fix: import CHANNEL_IDS directly from channels/ids.js (the leaf module with
zero heavy dependencies) and normalizeChatChannelId from channels/chat-meta.js.

Fixes #48832

Co-authored-by: Brad Groux <[email protected]>
steipete pushed a commit to duncanita/openclaw that referenced this pull request Apr 4, 2026
…aw#48832) (openclaw#60061)

schema.ts and validation.ts imported CHANNEL_IDS from channels/registry.js,
which re-exports from channels/ids.js but also imports plugins/runtime.js.
When the bundler resolves this dependency graph, the re-exported CHANNEL_IDS
can be undefined at the point config/validation.ts evaluates (temporal dead
zone), causing 'CHANNEL_IDS is not iterable' on startup.

Fix: import CHANNEL_IDS directly from channels/ids.js (the leaf module with
zero heavy dependencies) and normalizeChatChannelId from channels/chat-meta.js.

Fixes openclaw#48832

Co-authored-by: Brad Groux <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

maintainer Maintainer-authored PR size: XS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]:[Windows] Module initialization error: CHANNEL_IDS not iterable on startup

2 participants