jackwener/OpenCLI · warning
[warn] Image base64 payload is ${(base64.length / 1024 / 102
Error message
[warn] Image base64 payload is ${(base64.length / 1024 / 1024).toFixed(1)}MB. This may fail with the browser bridge. Update the extension to v1.6+ for CDP-based upload, or compress the image before attaching. What it means
attachComposerImage warns when the base64-encoded image read from disk exceeds ~500KB, because large payloads may fail when injected through the browser bridge's page.evaluate path. Older extensions (< v1.6) lack CDP-based upload, so big attachments can silently fail or time out.
Source
Thrown at clis/twitter/utils.js:155
const msg = err instanceof Error ? err.message : String(err);
if (!isRecoverableFileInputError(msg)) {
throw new Error(`Image upload failed: ${msg}`);
}
// setFileInput not supported by extension — fall through to base64 fallback.
}
}
if (!uploaded) {
const ext = path.extname(absImagePath).toLowerCase();
const mimeType = ext === '.png'
? 'image/png'
: ext === '.gif'
? 'image/gif'
: ext === '.webp'
? 'image/webp'
: 'image/jpeg';
const base64 = fs.readFileSync(absImagePath).toString('base64');
if (base64.length > 500_000) {
console.warn(`[warn] Image base64 payload is ${(base64.length / 1024 / 1024).toFixed(1)}MB. ` +
'This may fail with the browser bridge. Update the extension to v1.6+ for CDP-based upload, ' +
'or compress the image before attaching.');
}
const upload = await page.evaluate(`
(() => {
const input = document.querySelector(${JSON.stringify(fileInputSelector)});
if (!input) return { ok: false, error: 'No file input found on page' };
const binary = atob(${JSON.stringify(base64)});
const bytes = new Uint8Array(binary.length);
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
const dt = new DataTransfer();
const blob = new Blob([bytes], { type: ${JSON.stringify(mimeType)} });
dt.items.add(new File([blob], ${JSON.stringify(path.basename(absImagePath))}, { type: ${JSON.stringify(mimeType)} }));
let assigned = false;
try {View on GitHub (pinned to 49907e53dc)
Solutions
- Update the browser extension to v1.6+ for CDP-based upload which handles large payloads
- Compress/resize the image before attaching (e.g., convert to JPEG/WebP, scale to ≤1600px)
- If the attach then fails, retry after compressing rather than increasing timeouts
- Check the extension version in the browser and reload it if outdated
Example fix
// before npx sharp -i photo.png -o photo-small.jpg resize 1280 opencli twitter attach-image photo-small.jpg // after (compressed) # attach the compressed file opencli twitter attach-image photo-small.jpg
Defensive patterns
Strategy: validation
Validate before calling
const stat = fs.statSync(absImagePath);
if (stat.size > 375 * 1024) {
console.warn('Image too large for browser bridge; compress first.');
} Try / catch
try {
await attachComposerImage(page, imagePath);
} catch (err) {
if (err instanceof CliError && /upload|payload/i.test(err.message)) {
await attachComposerImage(page, compressImage(imagePath)); // retry compressed
}
} Prevention
- Compress/resize images to under ~375KB before attaching
- Update the browser extension to v1.6+ (CDP-based upload)
- Prefer JPEG/WebP over PNG for photos
- Watch for the '[warn] Image base64 payload' line and treat it as a signal to compress
When it happens
Trigger: Attaching an image whose base64 string length > 500,000 characters (roughly a source file over ~375KB) via clis/twitter attach-image with a pre-v1.6 extension.
Common situations: Attaching high-resolution photos or uncompressed screenshots, GIFs several MB in size, older browser extension installed, images not pre-optimized before attach.
Related errors
- [warn] Total image payload is ${(totalBytes / 1024 / 1024).t
- Too many images: ${paths.length} (max ${MAX_IMAGES})
- Unsupported image format "${ext}". Supported: jpg, png, gif,
- twitter image upload
- 12306 tk auth cookie missing
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/852fa2997741e869.
Report an issue: GitHub.