Skip to content

[BUG] Shell Integration Error persists after long sessions — dead terminal reuse in getOrCreateTerminal() #704

Description

@myk1yt

A Note from the User

This is a message from me, a human user. I asked AI to handle the rest of the issue report.

I tried to patch the problems I encountered while using Zoo Code myself. The patches may be incomplete or may not work correctly. Please, the bug fix team, judge them directly. I hope Zoo Code continues to grow and mature.


Problem

After long sessions (30+ minutes), execute_command repeatedly returns "Command failed to execute in terminal due to a shell integration error." The failure rate increases dramatically as the session progresses.

Context

  • OS: Windows 11, PowerShell 5.1
  • Zoo Code Version: v3.63.100188
  • API Provider: OpenAI Compatible
  • Model: mimo-v2.5-pro
  • Affected: Multiple projects (ZooChat, Emebala, myownsettings)

Reproduction Steps

  1. Open Zoo Code and execute multiple commands (works normally)
  2. Maintain session for 30+ minutes with repeated command execution
  3. Create multiple terminal instances
  4. Subsequent commands trigger "shell integration error"

Expected Result

Commands should execute successfully.

Actual Result

"Command failed to execute in terminal due to a shell integration error" is returned. Retrying the same command does not help.

Relevant Logs

[PATCH] execa fallback attempted. Original message: Command failed to execute in terminal due to a shell integration error.

Root Cause Analysis

The getOrCreateTerminal() method at byte offset 14,562,575 in extension.js reuses dead terminals:

static async getOrCreateTerminal(e, r, a="vscode") {
  let o = this.getAllTerminals(),
      s = a === "vscode" ? Pn.getReuseKey() : a,
      n;
  return r && (n = o.find(u =>
    u.busy || u.taskId !== r || u.provider !== a || u.reuseKey !== s ? !1 : ...
  ));
  // If busy=false and taskId/reuseKey match, dead terminals are also reused
}

When a terminal loses its internal state (PID gone, shell integration timeout), Zoo Code still reuses it because taskId + reuseKey match.

Minified Alias Mapping (extension.js)

Original Minified Byte Offset
selectTerminalProvider MZs 14,717,666
canRetryShellIntegrationError BZs 14,717,646
ShellIntegrationError JM 14,717,640
executeCommandInTerminal zyi 14,720,177
vscodeTerminal Pn 12,889,514
TerminalRegistry h0 14,560,517

Applied Patch

We applied a community patch that adds a forceNewTerminal option:

Change 1: MZs() — add forceNewTerminal parameter

function MZs(t, e) {
  let r = !t && Pn.isActiveShellCmdExe();
  return { terminalProvider: t || r || e ? "execa" : "vscode", isCmdExeFallback: r }
}

Change 2: zyi() — add forceNewTerminal to destructure

async function zyi(t, {executionId: e, command: r, customCwd: a,
                       terminalShellIntegrationDisabled: o = !0,
                       forceNewTerminal: __fn = !1,
                       commandExecutionTimeout: s = 0, agentTimeout: n = 0}) {

Change 3-6: Pass forceNewTerminal through the call chain

let Y = await h0.getOrCreateTerminal(c, t.taskId, E, __fn);
// In catch/retry branches:
await zyi(r, {...y, terminalShellIntegrationDisabled: !0, forceNewTerminal: !0})

Change 7: Pn constructor — explicit PowerShell shellPath fallback

let explicitShell = process.platform === "win32"
  ? (process.env.SystemRoot || "C:\\Windows") + "\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"
  : (process.env.SHELL || "/bin/bash");
n.shellPath = explicitShell;

Patch Verification

Check Result
Node.js --check ✅ PASSED
Size change +365 bytes

Recommended Official Fix

Add terminal validity check in getOrCreateTerminal():

static async getOrCreateTerminal(e, r, a="vscode", forceNew=false) {
  if (forceNew) return this.createTerminal(e, a);
  let o = this.getAllTerminals(),
      s = a === "vscode" ? Pn.getReuseKey() : a, n;
  if (r) {
    n = o.find(u => {
      if (u.busy || u.taskId !== r || u.provider !== a || u.reuseKey !== s) return false;
      if (u.terminal?.exitStatus !== undefined) return false;
      return true;
    });
  }
  return n || this.createTerminal(e, a);
}

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