davila7/claude-code-templates · error · Error
Invalid response from x0.at: ${uploadUrl || stderr}
Error message
Invalid response from x0.at: ${uploadUrl || stderr} What it means
Thrown by uploadToX0() in cli-tool/src/session-sharing.js when the x0.at file-hosting service returns a response that is empty or does not start with 'http'. The tool uploads a session archive with curl and expects the plain-text share URL on stdout; anything else (an HTML error page, a rate-limit message, an empty body) fails this check. The error message includes whatever was received (or stderr) to help diagnose the service response.
Source
Thrown at cli-tool/src/session-sharing.js:241
await fs.writeFile(tmpFile, JSON.stringify(sessionData, null, 2), 'utf8');
console.log(chalk.gray(`📁 Created temp file: ${tmpFile}`));
console.log(chalk.gray(`📤 Uploading to x0.at...`));
// Upload to x0.at using curl with form data
// x0.at API: curl -F'file=@yourfile.png' https://x0.at
// Response: Direct URL in plain text
const { stdout, stderr } = await execAsync(
`curl -s -F "file=@${tmpFile}" ${this.uploadUrl}`,
{ maxBuffer: 10 * 1024 * 1024 } // 10MB buffer
);
// x0.at returns URL directly in plain text
const uploadUrl = stdout.trim();
// Validate response
if (!uploadUrl || !uploadUrl.startsWith('http')) {
throw new Error(`Invalid response from x0.at: ${uploadUrl || stderr}`);
}
console.log(chalk.green(`✅ Uploaded to x0.at successfully`));
console.log(chalk.yellow(`⚠️ Files kept for 3-100 days (based on size)`));
console.log(chalk.gray(`🔓 Note: Files are not encrypted by default`));
// Clean up temp file
await fs.remove(tmpFile);
return uploadUrl;
} catch (error) {
// Clean up temp file on error
await fs.remove(tmpFile).catch(() => {});
throw error;
}
}
/**View on GitHub (pinned to a0851ed10c)
Solutions
- Check the message payload: if it contains HTML or an error status, x0.at rejected the upload — shrink the session file or retry later
- Verify curl is installed and reachable: curl -I https://x0.at
- Retry after a short delay — x0.at rate-limits or has transient outages
- If the session is large, prune old messages from the session before sharing
Example fix
// before
if (!uploadUrl || !uploadUrl.startsWith('http')) {
throw new Error(`Invalid response from x0.at: ${uploadUrl || stderr}`);
}
// after
if (!uploadUrl || !uploadUrl.startsWith('http')) {
throw new Error(`Invalid response from x0.at: ${uploadUrl || stderr || 'empty response (service may be down or file too large)'}`);
} Defensive patterns
Strategy: retry
Validate before calling
const https = require('https');
https.get('https://x0.at', res => console.log('x0.at reachable:', res.statusCode)); Try / catch
try {
const url = await sharer.uploadToX0(file);
} catch (e) {
if (/Invalid response from x0\.at/.test(e.message)) {
await sleep(5000);
return retry(attempts - 1); // transient service errors are common
}
throw e;
} Prevention
- Keep shared session archives small enough for x0.at's limits
- Check service availability before batch-sharing sessions
- Treat x0.at as best-effort: surface the raw response in the error to the user
When it happens
Trigger: Calling shareSession()/uploadToX0() when x0.at is down, rate-limiting, returns an HTML error page (e.g. '413 Request Entity Too Large'), or when curl fails silently and stdout is empty. Also triggered if the session archive exceeds x0.at's size limit.
Common situations: Sharing a very large session file that exceeds x0.at's upload cap; x0.at temporarily offline or behind a maintenance page; corporate proxies stripping the response body; curl not installed so stdout is empty.
Related errors
- Download failed: ${stderr}
- GitHub API error: ${response.status}
- Invalid session file - corrupted or not a Claude Code sessio
- Invalid session file - missing version
- Invalid session file - missing conversation data
AI-assisted analysis of davila7/claude-code-templates@a0851ed10c (2026-08-28).
Data as JSON: /api/errors/66eec2d632c821ce.
Report an issue: GitHub.