Skip to content

Execution failed: request ended without sending any chunks #641

@fazai-ng

Description

@fazai-ng

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions