davila7/claude-code-templates · error · Error

Download failed: ${stderr}

Error message

Download failed: ${stderr}

What it means

Thrown by downloadSession() in cli-tool/src/session-sharing.js when curl was used to fetch a shared session URL and produced stderr output with no stdout. This means the download itself failed at the transport level (DNS failure, TLS error, 404, connection refused) rather than returning corrupt data. The curl stderr text is embedded in the message.

Source

Thrown at cli-tool/src/session-sharing.js:313

      console.error(chalk.red('❌ Failed to clone session:'), error.message);
      throw error;
    }
  }

  /**
   * Download session data from URL
   * @param {string} url - URL to download from
   * @returns {Promise<Object>} Session data
   */
  async downloadSession(url) {
    try {
      // Use curl to download (works with x0.at and other services)
      const { stdout, stderr } = await execAsync(`curl -L "${url}"`, {
        maxBuffer: 50 * 1024 * 1024 // 50MB buffer for large sessions
      });

      if (stderr && !stdout) {
        throw new Error(`Download failed: ${stderr}`);
      }

      // Parse JSON response
      const sessionData = JSON.parse(stdout);
      return sessionData;
    } catch (error) {
      if (error.message.includes('Unexpected token')) {
        throw new Error('Invalid session file - corrupted or not a Claude Code session');
      }
      throw error;
    }
  }

  /**
   * Validate session data structure
   * @param {Object} sessionData - Session data to validate
   * @throws {Error} If validation fails
   */

View on GitHub (pinned to a0851ed10c)

Solutions

  1. Verify the URL opens in a browser — x0.at deletes files after 3-100 days, so expired links are the most common cause
  2. Test connectivity: curl -L "<url>" and read the stderr/code
  3. If behind a proxy, ensure HTTPS_PROXY/https_proxy env vars are set so curl can traverse it
  4. Ask the sender to re-upload the session if the link has expired

Example fix

// before
const { stdout, stderr } = await execAsync(`curl -L "${url}"`);
if (stderr && !stdout) {
  throw new Error(`Download failed: ${stderr}`);
}

// after
const { stdout, stderr } = await execAsync(`curl -fL --retry 2 "${url}"`);
if (stderr && !stdout) {
  throw new Error(`Download failed for ${url}: ${stderr}`);
}
Defensive patterns

Strategy: retry

Validate before calling

// Pre-check the URL is alive before downloading
const { stdout } = await execAsync(`curl -sIL -o /dev/null -w '%{http_code}' "${url}"`);
if (stdout.trim() !== '200') throw new Error(`Link not downloadable (HTTP ${stdout.trim()}) — possibly expired`);

Try / catch

try {
  const data = await downloader.downloadSession(url);
} catch (e) {
  if (/^Download failed/.test(e.message)) {
    // expired link or network issue — tell user and stop, no point parsing
    throw new Error(`Session link unavailable: ${e.message}`);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling downloadSession(url)/sessionData with a URL that no longer exists (x0.at files expire after 3-100 days), a mistyped URL, no network connectivity, or a TLS-intercepting proxy that breaks the connection.

Common situations: Trying to clone a session whose x0.at link has expired; air-gapped or proxy-filtered environments where curl cannot resolve or reach the host; URL copied with trailing characters or quotes.

Related errors


AI-assisted analysis of davila7/claude-code-templates@a0851ed10c (2026-08-28). Data as JSON: /api/errors/9ffc36d48c919438. Report an issue: GitHub.