Skip to content

Windows: letta channels configure fails with spawn EINVAL — npm spawn missing shell: true #1997

@ezra-letta

Description

@ezra-letta

Summary

letta channels configure <telegram|slack|discord> fails on Windows during the channel runtime install step with Error: spawn EINVAL. The spawn call in installChannelRuntime invokes npm without shell: true, but on Windows npm is a .cmd shim. Node 20+ refuses to spawn .cmd files directly without the shell flag (CVE-2024-27980 hardening), so the install never runs.

This blocks first-time channel setup on Windows for all three supported channel types, since they share the same installer path.

Reproduction

  1. Fresh npm install -g @letta-ai/letta-code on Windows (verified on 0.24.8)
  2. letta channels configure discord (or telegram, or slack)
  3. After the setup intro prints, install kicks off and immediately throws

Stack trace (from a user, Letta Code 0.24.8 on Windows)

[Channels] Installing Discord runtime dependencies (discord.js)...
node:internal/child_process:421
    throw new ErrnoException(err, 'spawn');
          ^

Error: spawn EINVAL
    at ChildProcess.spawn (node:internal/child_process:421:11)
    at spawn (node:child_process:796:9)
    at file:///C:/Users/.../node_modules/@letta-ai/letta-code/letta.js:41515:18
    at new Promise (<anonymous>)
    at installChannelRuntime (.../letta.js:41514:9)
    at async ensureChannelRuntimeInstalled (.../letta.js:41536:3)
    at async runDiscordSetup (.../letta.js:44941:5)
    at async handleConfigure (.../letta.js:164068:19)
    at async main (.../letta.js:168425:28) {
  errno: -4071,
  code: 'EINVAL',
  syscall: 'spawn'
}

Root cause

letta.js:41515 calls spawn('npm', [...args], { ... }) without shell: true. On Windows, npm resolves to npm.cmd; post-CVE-2024-27980 Node refuses to spawn .cmd/.bat files without shell: true.

Suggested fix

Pass shell: process.platform === 'win32' (or shell: true unconditionally — it's safe here since the args are controlled internally) in the spawn options inside installChannelRuntime.

Probably also worth adding --legacy-peer-deps to the npm args, since the current published package.json has an ink peer-dep conflict that ERESOLVEs an in-place install (filed separately).

Workaround for users until fixed

Manually install the channel runtime into letta-code's own node_modules:

cd "$env:APPDATA\npm\node_modules\@letta-ai\letta-code"
npm install discord.js@14.18.0 --legacy-peer-deps   # or @grammyjs/grammy for Telegram, @slack/bolt for Slack
letta channels configure <channel>

The configure command's presence check is then satisfied and it proceeds to the bot-token / pairing prompts.

Affected versions

Confirmed: 0.24.8 (Windows). Likely all earlier versions in the channels-shipped era — same code path.

Related

  • Discovered while assisting a user with Discord channel setup; same EINVAL would fire for Telegram and Slack on a fresh Windows install.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions