davila7/claude-code-templates · error · Error

Invalid session file - corrupted or not a Claude Code sessio

Error message

Invalid session file - corrupted or not a Claude Code session

What it means

Thrown by downloadSession() in cli-tool/src/session-sharing.js when JSON.parse of the downloaded body fails with a 'Unexpected token' SyntaxError. That means the URL returned valid HTTP content that is not JSON — typically an HTML error page, a plaintext notice, or a truncated file — so it cannot be a Claude Code session export.

Source

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

   * @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
   */
  validateSessionData(sessionData) {
    if (!sessionData.version) {
      throw new Error('Invalid session file - missing version');
    }

    if (!sessionData.conversation || !sessionData.conversation.id) {
      throw new Error('Invalid session file - missing conversation data');
    }

View on GitHub (pinned to a0851ed10c)

Solutions

  1. Open the URL in a browser and inspect what is actually returned — if it's HTML, the session file is gone or the URL is wrong
  2. Re-run the download (transient truncation on large files) and confirm Content-Length matches
  3. Get a fresh share link from the original session owner
  4. If you maintain the code, log the first 200 chars of stdout to see exactly what came back

Example fix

// before
const sessionData = JSON.parse(stdout);

// after
let sessionData;
try {
  sessionData = JSON.parse(stdout);
} catch (e) {
  throw new Error(`Invalid session file - corrupted or not a Claude Code session (got: ${stdout.slice(0, 120)})`);
}
Defensive patterns

Strategy: validation

Validate before calling

const raw = await fetchText(url);
const trimmed = raw.trim();
if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) {
  throw new Error('URL did not return JSON — likely an HTML error page');
}

Type guard

function looksLikeSessionJson(text) {
  const t = text.trim();
  return (t.startsWith('{') || t.startsWith('[')) && !/^<!doctype html/i.test(t);
}

Try / catch

try {
  return await downloader.downloadSession(url);
} catch (e) {
  if (e.message.includes('Invalid session file - corrupted')) {
    throw new Error('The link returned non-JSON content (probably expired or wrong URL)');
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling downloadSession(url) where the URL returns HTML (404 page, x0.at notice page) or arbitrary text. The curl download 'succeeds' (stdout non-empty) but the body is not JSON.

Common situations: Following a link to a file x0.at already deleted but that now serves an HTML notice; pasting a generic URL instead of the session share URL; truncated download of a large session that cut off mid-JSON.

Understand the failure class

Background: "Invalid JSON response" and "Failed to parse response" errors: when an API answers 200 but the body isn't the JSON your library expected — this error's family across 28 libraries.

Related errors


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