copilot-cli icon indicating copy to clipboard operation
copilot-cli copied to clipboard

Execution failed: request ended without sending any chunks

Open fazai-ng opened this issue 2 months ago • 0 comments

Issue Description

Error: Execution failed: request ended without sending any chunks

Context

  • Tool: GitHub Copilot CLI (terminal agent)
  • Session: Long-running interactive session
  • Trigger: Tool execution (bash/file operations) interrupted mid-stream
  • Impact: Abrupt termination with no partial output, unclear session state

Expected Behavior

  1. Proper timeout handling with configurable limits
  2. Graceful degradation when stream fails
  3. Buffer partial responses before streaming begins
  4. Clear error messages with actionable context
  5. Automatic retry with exponential backoff

Actual Behavior

  • Abrupt termination with generic error message
  • No partial output preserved or accessible
  • Session state unclear after error
  • No retry mechanism offered
  • User forced to restart conversation

Reproduction Steps

  1. Start long-running Copilot CLI session
  2. Execute complex tool operation (e.g., file operations, bash commands)
  3. Network hiccup or API timeout occurs mid-stream
  4. Observe generic "request ended without sending any chunks" error

Suggested Fix

// Add stream buffering and timeout guards
async function executeToolWithRetry(tool, params, options = {}) {
  const { timeout = 120000, maxRetries = 3, backoff = 2000 } = options;
  const buffer = [];
  
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const stream = await tool.execute(params);
      
      // Buffer initial chunks before streaming to user
      const timeoutPromise = new Promise((_, reject) =>
        setTimeout(() => reject(new Error('Timeout')), timeout)
      );
      
      for await (const chunk of stream) {
        buffer.push(chunk);
        if (buffer.length >= 3) break; // Buffer first 3 chunks
      }
      
      // Stream rest to user
      for (const chunk of buffer) yield chunk;
      for await (const chunk of stream) yield chunk;
      
      return; // Success
      
    } catch (error) {
      if (attempt === maxRetries) {
        // Provide buffered content even on failure
        if (buffer.length > 0) {
          yield "⚠️  Partial result (connection interrupted):\n";
          for (const chunk of buffer) yield chunk;
        }
        throw new Error(\`Failed after \${maxRetries} attempts: \${error.message}\`);
      }
      
      await new Promise(resolve => setTimeout(resolve, backoff * attempt));
    }
  }
}

Environment

  • OS: Linux (Fedora)
  • Node.js: v22.20.0
  • Copilot CLI: Running as daemon process
  • Session type: Interactive terminal

Reported by: Roger Luft
Email: [email protected]
Research: https://fcc.rogerluft.com.br
Date: 2025-11-21

fazai-ng avatar Nov 22 '25 01:11 fazai-ng