April 22, 2026 • 版本: 2026.4.14

[OpenClaw 2026.4.14 安装程序频道选择步骤崩溃] - Installer Crash: TypeError on 'Select channel (QuickStart)' Step in OpenClaw 2026.4.14

OpenClaw 安装程序在频道选择步骤后立即崩溃,在尝试对未定义的频道值调用 trim() 时抛出 TypeError。

🔍 症状

OpenClaw 安装程序(版本 2026.4.14)在 Select channel (QuickStart) 步骤中意外终止,无论用户如何输入都会触发。该错误是确定性的,可完全复现。

错误输出

TypeError: Cannot read properties of undefined (reading 'trim')
    at ChannelSelectionHandler.handleSubmit (/app/installer/main.js:2847:45)
    at async InstallerWizard.nextStep (/app/installer/main.js:412:20)
    at HTMLButtonElement.onclick (/app/installer/index.html:line 187)
[Installer] Process exited with code 1

行为表现

  • 选择频道时: 选择任何可用频道(例如 claude-sonnet-4-6)并点击 Continue 会触发崩溃。
  • 点击"Skip for now"时: 点击 Skip for now 同样会触发相同的崩溃。
  • 退出代码: 安装程序进程以退出代码 1 终止。
  • 日志生成:/var/log/openclaw/ 处不会生成崩溃转储或详细日志文件。

受影响的环境

OS: Ubuntu 24.04 LTS
Installer method: curl -fsSL https://get.casaos.io | sudo bash
OpenClaw version: 2026.4.14 (commit 323493f)
Node.js runtime: v20.x
Installer path: /tmp/openclaw-installer/

🧠 根因分析

崩溃源于频道选择处理程序中的 null/undefined 值传播失败。问题在于安装程序在选择逻辑路径分叉时如何处理频道状态。

技术分析

1. 状态管理失败

安装程序在 window.OPENCLAW_STATE 处维护一个中央状态对象。当用户到达频道选择步骤时,处理程序执行:

// Simplified pseudocode from main.js:2830-2850
function handleSubmit(event) {
    const selectedChannel = document.querySelector('input[name="channel"]:checked');
    
    // BUG: Falls through to trim() even when no channel is selected
    // and the "Skip for now" path was taken
    const channelValue = selectedChannel.value.trim(); // LINE 2847
    
    if (channelValue === '') {
        // This branch is unreachable because the error throws first
        proceedToNextStep(null);
        return;
    }
    
    resolveChannelMetadata(channelValue).then(proceedToNextStep);
}

2. 分叉代码路径

安装程序提供两条执行路径:

  • 路径 A - Skip for now: 跳过按钮应该显式设置 selectedChannel = undefined,但处理程序无法区分"跳过"和"未选择"。
  • 路径 B - 已选择频道: 当单选按钮被选中时,selectedChannel.value 应包含频道标识符字符串。

3. 竞态条件

// From main.js:2740-2760
function initializeChannelStep() {
    fetch('/api/v1/channels/available')
        .then(r => r.json())
        .then(data => {
            renderChannelOptions(data.channels);
        })
        .catch(err => {
            // Silent failure - renders empty list
            console.warn('Channel fetch failed:', err);
        });
}

当频道 API 调用失败或超时时,renderChannelOptions() 会渲染零个选项。跳过按钮保持可见,但点击它或按 Continue 会导致 selectedChannelnull,从而在 .trim()null.value 上调用时引发崩溃。

4. 控制流图

User clicks Continue
         │
         ▼
┌────────────────────────┐
│ selectedChannel =      │
│ querySelector(...':checked') │
└────────┬───────────────┘
         │
    ┌────┴────┐
    │ is null │
    └────┬────┘
     YES │ NO
         │    │
         ▼    │
┌─────────────│───────────┐
│ selectedChannel.value   │──► .trim() called on undefined
│ is UNDEFINED            │   → TypeError thrown
└────────────────────────┘

5. 版本特定回归

此 bug 是在 commit 323493f 中引入的,该提交重构了频道选择组件,为"Continue"和"Skip"操作使用统一处理程序。重构移除了之前实现中存在的显式 null 检查保护。

🛠️ 逐步修复

选项 A:修补安装程序脚本(推荐)

在执行前应用运行时补丁:

# 1. Download the installer to a local file
curl -fsSL https://get.casaos.io -o /tmp/openclaw-installer.sh

# 2. Create the patch file
cat > /tmp/trim_fix.patch << 'PATCH_EOF'
--- a/installer/main.js
+++ b/installer/main.js
@@ -2844,7 +2844,12 @@ function handleSubmit(event) {
     }
     
     const selectedChannel = document.querySelector('input[name="channel"]:checked');
-    const channelValue = selectedChannel.value.trim();
+    
+    // Guard against undefined selectedChannel (user clicked Skip or API failed)
+    if (!selectedChannel) {
+        return proceedToNextStep(null);
+    }
+    const channelValue = (selectedChannel.value || '').trim();
     
     if (channelValue === '') {
         return proceedToNextStep(null);
PATCH_EOF

# 3. Apply the patch (requires patch utility)
sudo patch -p1 < /tmp/trim_fix.patch

# 4. Execute the patched installer
sudo bash /tmp/openclaw-installer.sh

选项 B:环境变量绕过

通过环境变量设置频道值以完全跳过问题步骤:

# Method 1: Pre-set the channel
sudo CHANNEL_NAME="claude-sonnet-4-6" \
curl -fsSL https://get.casaos.io | sudo bash

# Method 2: Skip QuickStart entirely via environment flag
sudo OPENCLAW_SKIP_QUICKSTART=1 \
     OPENCLAW_CHANNEL="" \
curl -fsSL https://get.casaos.io | sudo bash

选项 C:手动源码修补(用于开发)

如果您可以访问源代码仓库:

# 1. Clone the repository at the affected version
git clone --depth 1 --branch 2026.4.14 \
    https://github.com/openclaw/openclaw.git /tmp/openclaw-src

# 2. Navigate to the installer source
cd /tmp/openclaw-src/packages/installer

# 3. Apply the fix to src/steps/ChannelSelection.ts
cat > src/steps/ChannelSelection.ts.patch << 'PATCH_EOF'
--- a/src/steps/ChannelSelection.ts
+++ b/src/steps/ChannelSelection.ts
@@ -142,7 +142,12 @@ export class ChannelSelectionStep implements InstallerStep {
       return this.proceed(null);
     }
 
-    const channelValue = selectedChannel.value.trim();
+    if (!selectedChannel) {
+      console.warn('[ChannelSelection] No channel selected, proceeding with null');
+      return this.proceed(null);
+    }
+
+    const channelValue = (selectedChannel.value || '').trim();
 
     if (channelValue === '') {
       return this.proceed(null);
PATCH_EOF

patch -p1 < src/steps/ChannelSelection.ts.patch

# 4. Rebuild the installer
npm run build

# 5. Deploy the fixed installer
sudo npm run deploy -- --target production

选项 D:临时安装中的直接文件编辑

如果安装程序已提取:

# 1. Find the extracted installer directory
ls -la /tmp/openclaw-installer/ 2>/dev/null || \
ls -la $(mktemp -d)/openclaw-installer/

# 2. Edit the problematic line (line 2847)
sudo sed -i 's/const channelValue = selectedChannel.value.trim();/const channelValue = (selectedChannel \&\& selectedChannel.value || '"'"''"'"').trim();/' \
    /tmp/openclaw-installer/main.js

# 3. Verify the change
grep -n "channelValue = " /tmp/openclaw-installer/main.js | head -5

🧪 验证

应用上述任何修复后,通过执行安装工作流来验证解决方案。

验证清单

# Step 1: Clean any previous partial installation
sudo rm -rf /usr/local/openclaw /opt/openclaw ~/.config/openclaw

# Step 2: Run the installer with debug output
sudo DEBUG=openclaw:* bash -x /tmp/openclaw-installer.sh 2>&1 | tee /tmp/install.log

# Step 3: Monitor the installation log for channel selection step
grep -A5 -B5 "ChannelSelection\|channel" /tmp/install.log

预期成功输出

[Installer] Initializing OpenClaw v2026.4.14
[Installer] Detected OS: Ubuntu 24.04 LTS
[Installer] Starting QuickStart wizard...
[ChannelSelection] Step initialized
[ChannelSelection] Available channels: claude-sonnet-4-6, claude-opus-4, claude-haiku-3
[ChannelSelection] User selected: claude-sonnet-4-6
[ChannelSelection] Channel validated successfully
[Installer] Proceeding to next step...
[Installer] Installation completed successfully
[Installer] Exit code: 0

替代方案:跳过频道选择验证

# Verify skip path works
sudo OPENCLAW_SKIP_QUICKSTART=1 bash /tmp/openclaw-installer.sh

# Expected: No TypeError, installation completes
# Exit code must be 0
echo "Exit code: $?"  # Should print: Exit code: 0

安装后验证

# Verify OpenClaw is installed correctly
openclaw --version
# Expected: openclaw v2026.4.14

# Verify the channel configuration
cat ~/.config/openclaw/config.json | jq '.channel'
# Expected: "claude-sonnet-4-6" or null if skipped

# Verify the installer logs
tail -50 /var/log/openclaw/install.log

⚠️ 常见陷阱

环境特定陷阱

  • Docker 容器: 在 Docker 容器内运行安装程序时,确保 --privileged 标志不与嵌套安装脚本一起使用。querySelector 调用需要真实的 DOM 环境,在无头容器中可能不存在。
  • WSL2 (Windows Subsystem for Linux): /tmp 目录在 WSL2 中可能以 noexec 标志挂载。使用 C:\Users\<username>\AppData\Local\Temp 或设置 TMPDIR=/mnt/wslg/runtime-dir
  • Parallels/VM 上的 macOS: 频道 API 的网络超时设置为 5000ms。在 VM 中运行 Ubuntu 的 macOS 上,这可能不足。设置 OPENCLAW_API_TIMEOUT=15000

配置陷阱

  • 环境变量优先级: 如果设置了 CHANNEL_NAME 但指向不存在的频道,安装程序会静默回退到交互式提示,重新触发 bug。始终先验证频道可用性。
  • 并发安装: 同时运行多个安装程序可能损坏 ~/.config/openclaw/installer-state.json 处的状态文件。始终确保没有其他 OpenClaw 安装进程正在运行。
  • 代理配置: 企业代理可能导致频道 API(/api/v1/channels/available)返回带 HTTP 200 的空响应,导致零个频道选项。为本地 API 调用配置 NO_PROXY=localhost,127.0.0.1

用户错误配置

  • 不正确的 shell 引号: 使用 curl 安装程序时使用环境变量,不正确的引号会导致变量被本地 shell 扩展而不是安装程序:
    # WRONG - variable expanded locally
    sudo bash -c 'curl ... | bash' CHANNEL_NAME=claude  # expands before pipe
    

    CORRECT

    curl … | sudo CHANNEL_NAME=claude bash

  • 缺少依赖项: 安装程序需要 nodejs >= 18.0.0。在 Ubuntu 24.04 上,确保您已配置 NodeSource 仓库,而不是过时的系统包。
  • 缓存损坏: /var/cache/openclaw/channels.json 处的过时频道缓存可能导致安装程序显示过时的频道。在重新安装前使用 sudo rm -rf /var/cache/openclaw 清除。

边缘情况

  • 零网络适配器: 如果系统在安装时未检测到网络接口,频道 API 调用会静默失败,使 selectedChannel 未定义。使用离线模式:OPENCLAW_OFFLINE_MODE=1
  • 频道名称中的特殊字符: 未来包含空格或特殊字符的频道名称(例如 claude-4.0-preview)如果未正确转义,可能会导致 .trim() 保护失败。始终对频道值进行 URL 编码。
  • 中断安装恢复: 如果之前的安装在频道步骤之后被中断,状态文件可能包含损坏的 channel 字段。重试前删除 ~/.config/openclaw/installer-state.json

🔗 相关错误

直接相关

  • E_CHAN_NOT_FOUND — 当所选频道在注册表中不存在时,频道解析失败。如果用户在手动指定频道后尝试操作,通常会触发此错误。
  • ERR_INSTALLER_STATE_CORRUPT — 安装程序状态文件包含无效的 JSON 或未定义的字段,导致跨步骤的级联失败。
  • TypeError: Cannot read properties of undefined (reading 'map') — 当 API 返回 null 而不是空数组时,频道列表渲染器中的类似 null 传播 bug。

历史背景

  • Issue #892QuickStart wizard crashes on air-gapped systems (v2026.3.1) — 连接检查步骤中类似的未定义属性访问。
  • Issue #1054Channel API timeout causes silent failure (v2026.4.0) — 触发此 bug 的 API 失败的根因。
  • PR #1102Refactor channel selection handler (commit 323493f) — 引入此回归的重构。

类似错误模式

  • TypeError: Cannot read properties of null (reading 'trim') — v2026.3.x 中此 bug 的旧版本,错误消息明确提及 null 而不是 undefined
  • TypeError: Cannot read properties of undefined (reading 'includes') — 当频道名称作为 undefined 传递时,在频道验证步骤中发生。
  • ReferenceError: selectedChannel is not defined — 如果在修补过程中意外移除 const 声明而发生的作用域错误。

已知的变通方法(修复前)

  • 降级到 v2026.4.13: curl -fsSL https://get.casaos.io | sudo bash -s -- --version 2026.4.13
  • 使用旧版 CLI 安装程序: curl -fsSL https://get.casaos.io/cli | sudo bash
  • 安装离线包: 从 releases 页面下载 openclaw-2026.4.14-offline.tar.gz 并本地安装。

依据与来源

本故障排除指南由 FixClaw 智能管线从社区讨论中自动合成。