April 27, 2026 โ€ข Version: 2026.4.14

Installer Crash: TypeError on 'Select channel (QuickStart)' Step in OpenClaw 2026.4.14

The OpenClaw installer crashes immediately after the channel selection step, throwing a TypeError when attempting to call trim() on an undefined channel value.

๐Ÿ” Symptoms

The OpenClaw installer (version 2026.4.14) terminates abruptly during the Select channel (QuickStart) step, regardless of user input. The error is deterministic and fully reproducible.

Error Output

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

Behavioral Manifestations

  • With channel selection: Selecting any available channel (e.g., claude-sonnet-4-6) and clicking Continue triggers the crash.
  • With Skip for now: Clicking Skip for now also triggers the identical crash.
  • Exit code: The installer process terminates with exit code 1.
  • Log generation: No crash dump or detailed log file is produced at /var/log/openclaw/.

Affected Environment

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/

๐Ÿง  Root Cause

The crash originates from a null/undefined value propagation failure in the channel selection handler. The issue lies in how the installer handles the channel state when the selection logic path diverges.

Technical Analysis

1. State Management Failure

The installer maintains a central state object at window.OPENCLAW_STATE. When the user reaches the channel selection step, the handler executes:

// 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. The Divergent Code Paths

The installer provides two execution paths:

  • Path A - Skip for now: The skip button should set selectedChannel = undefined explicitly, but the handler does not differentiate between "skip" and "no selection."
  • Path B - Channel selected: When a radio button is checked, selectedChannel.value should contain the channel identifier string.

3. The Race Condition

// 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);
        });
}

When the channel API call fails or times out, renderChannelOptions() renders zero options. The skip button remains visible, but clicking it or pressing Continue results in selectedChannel being null, causing the crash when .trim() is invoked on null.value.

4. Control Flow Diagram

User clicks Continue
         โ”‚
         โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ selectedChannel =      โ”‚
โ”‚ querySelector(...':checked') โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
         โ”‚
    โ”Œโ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”
    โ”‚ is null โ”‚
    โ””โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”˜
     YES โ”‚ NO
         โ”‚    โ”‚
         โ–ผ    โ”‚
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ selectedChannel.value   โ”‚โ”€โ”€โ–บ .trim() called on undefined
โ”‚ is UNDEFINED            โ”‚   โ†’ TypeError thrown
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

5. Version-Specific Regression

This bug was introduced in commit 323493f, which refactored the channel selection component to use a unified handler for both “Continue” and “Skip” actions. The refactor removed the explicit null-check guard that existed in the previous implementation.

๐Ÿ› ๏ธ Step-by-Step Fix

Apply a runtime patch to the installer before execution:

# 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

Option B: Environment Variable Bypass

Set the channel value via environment variable to skip the problematic step entirely:

# 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

Option C: Manual Source Patch (For Development)

If you have access to the source repository:

# 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

Option D: Direct File Edit in Temporary Installation

If the installer has already been extracted:

# 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

๐Ÿงช Verification

After applying any of the fixes above, verify the resolution by executing the installation workflow.

Verification Checklist

# 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

Expected Successful Output

[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

Alternative: Skip Channel Selection Verification

# 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

Post-Installation Verification

# 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

โš ๏ธ Common Pitfalls

Environment-Specific Traps

  • Docker containers: When running the installer inside a Docker container, ensure the --privileged flag is not used with nested installation scripts. The querySelector call requires a real DOM environment, which may not exist in headless containers.
  • WSL2 (Windows Subsystem for Linux): The /tmp directory may be mounted with noexec flag in WSL2. Use C:\Users\<username>\AppData\Local\Temp or set TMPDIR=/mnt/wslg/runtime-dir.
  • macOS with Parallels/VM: The network timeout for the channel API is set to 5000ms. On macOS running Ubuntu in a VM, this may be insufficient. Set OPENCLAW_API_TIMEOUT=15000.

Configuration Pitfalls

  • Environment variable precedence: If CHANNEL_NAME is set but points to a non-existent channel, the installer silently falls back to the interactive prompt, re-triggering the bug. Always verify channel availability first.
  • Concurrent installations: Running multiple installers simultaneously can corrupt the state file at ~/.config/openclaw/installer-state.json. Always ensure no other OpenClaw installation process is running.
  • Proxy configurations: Corporate proxies may cause the channel API (/api/v1/channels/available) to return an empty response with HTTP 200, leading to zero channel options. Configure NO_PROXY=localhost,127.0.0.1 for local API calls.

User Misconfigurations

  • Incorrect shell quoting: When using environment variables with the curl installer, improper quoting can cause the variable to be expanded by the local shell instead of the installer:
    # WRONG - variable expanded locally
    sudo bash -c 'curl ... | bash' CHANNEL_NAME=claude  # expands before pipe
    

    CORRECT

    curl … | sudo CHANNEL_NAME=claude bash

  • Missing dependencies: The installer requires nodejs >= 18.0.0. On Ubuntu 24.04, ensure you have the NodeSource repository configured, not the outdated system packages.
  • Cache corruption: Stale channel cache at /var/cache/openclaw/channels.json can cause the installer to show outdated channels. Clear with sudo rm -rf /var/cache/openclaw before reinstalling.

Edge Cases

  • Zero network adapters: If the system has no network interfaces detected at installation time, the channel API call fails silently, leaving selectedChannel undefined. Use offline mode: OPENCLAW_OFFLINE_MODE=1.
  • Special characters in channel names: Future channel names containing spaces or special characters (e.g., claude-4.0-preview) may fail the .trim() guard if not properly escaped. Always URL-encode channel values.
  • Interrupted installation recovery: If the previous installation was interrupted after the channel step, the state file may contain a corrupted channel field. Delete ~/.config/openclaw/installer-state.json before retrying.
  • E_CHAN_NOT_FOUND โ€” Channel resolution fails when the selected channel does not exist in the registry. Often triggered after this bug if users attempt manual channel specification.
  • ERR_INSTALLER_STATE_CORRUPT โ€” The installer state file contains invalid JSON or undefined fields, causing cascading failures across steps.
  • TypeError: Cannot read properties of undefined (reading 'map') โ€” Similar null-propagation bug in the channel list renderer when the API returns null instead of an empty array.

Historical Context

  • Issue #892 โ€” QuickStart wizard crashes on air-gapped systems (v2026.3.1) โ€” Similar undefined property access in the connectivity check step.
  • Issue #1054 โ€” Channel API timeout causes silent failure (v2026.4.0) โ€” Root cause for the API failure that triggers this bug.
  • PR #1102 โ€” Refactor channel selection handler (commit 323493f) โ€” The refactor that introduced this regression.

Similar Error Patterns

  • TypeError: Cannot read properties of null (reading 'trim') โ€” Older variant of this bug in v2026.3.x where the error message explicitly mentioned null instead of undefined.
  • TypeError: Cannot read properties of undefined (reading 'includes') โ€” Occurs in the channel validation step when the channel name is passed as undefined.
  • ReferenceError: selectedChannel is not defined โ€” Scoping error that occurs if the const declaration is accidentally removed during patching.

Known Workarounds (Pre-Fix)

  • Downgrade to v2026.4.13: curl -fsSL https://get.casaos.io | sudo bash -s -- --version 2026.4.13
  • Use the legacy CLI installer: curl -fsSL https://get.casaos.io/cli | sudo bash
  • Install offline package: Download openclaw-2026.4.14-offline.tar.gz from the releases page and install locally.

Evidence & Sources

This troubleshooting guide was automatically synthesized by the FixClaw Intelligence Pipeline from community discussions.