Skip to content

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

Open

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

Activity

  1. myk1yt commented on Jun 24, 2026

    @myk1yt
    ContributorAuthor

    Likely Resolved via Inline Terminal PowerShell Fix (#705)

    Whether this is a fundamental fix needs to be confirmed by the Zoo Code bug fix team.

    Analysis

    This issue reports that after long sessions (30+ minutes), execute_command repeatedly returns "shell integration error" because getOrCreateTerminal() reuses dead terminals whose internal state (PID, shell integration) has expired.

    The original problem code (extension.js offset ~14,562,575):

    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 : ...
      ));
      // Dead terminals are reused when busy=false and taskId/reuseKey match
    }

    Why Inline Terminal ON resolves this:

    When "Use Inline Terminal (recommended)" is ON, the execa provider is used instead of the VS Code integrated terminal:

    Mode Terminal Reuse Shell Integration #704 Risk
    Inline Terminal OFF Reuses VS Code terminals Depends on shell integration Dead terminal reuse causes errors
    Inline Terminal ON Creates new process per command Bypassed entirely No terminal reuse, no shell integration dependency

    With Inline Terminal ON:

    1. Each command runs as a fresh background process via execa — no terminal reuse at all
    2. Shell integration is completely bypassed — the "shell integration error" cannot occur
    3. Dead terminal accumulation is impossible — there are no persistent terminals to die

    Related Fix

    Issue #705 was resolved by making the Inline Terminal use PowerShell on Windows instead of cmd.exe:

    // Fixed execa shell selection (offset 14,556,931 in extension.js)
    shell: sW.getExecaShellPath() || (process.platform === "win32" ? "powershell.exe" : !0)

    With both Inline Terminal ON and PowerShell working correctly, the conditions that trigger #704 (dead terminal reuse + shell integration dependency) are eliminated.

    Recommendation

    We recommend using Inline Terminal ON with the PowerShell fix from #705. This sidesteps the getOrCreateTerminal() dead-reuse issue entirely. However, if the VS Code terminal mode is still needed, the exitStatus check in getOrCreateTerminal() should be added as described in the original issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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