toeverything/AFFiNE · error · ImageFormatNotSupported
image_format_not_supported
image_format_not_supported
Error message
Image format not supported: ${format} What it means
Thrown while processing an uploaded image attachment: the buffer's detected MIME type starts with 'image/', but processImage (resize to COPILOT_IMAGE_MAX_EDGE, convert to webp) rejected or crashed on the bytes. It wraps the failure as ImageFormatNotSupported with error code 'image_format_not_supported', naming the detected MIME in {format}. Typical causes are corrupted payloads, CMYJ/EXIF-heavy JPEGs, or exotic formats that the decoder cannot handle even though sniffing labeled them image/*.
Source
Thrown at packages/backend/server/src/plugins/copilot/conversation/inbox.ts:98
for (const blob of blobs) {
const uploaded = await this.storage.handleUpload(userId, blob);
const detectedMime =
sniffMime(uploaded.buffer, blob.mimetype)?.toLowerCase() ||
blob.mimetype;
let attachmentBuffer = uploaded.buffer;
let attachmentMimeType = detectedMime;
if (detectedMime.startsWith('image/')) {
try {
attachmentBuffer = await processImage(
uploaded.buffer,
COPILOT_IMAGE_MAX_EDGE,
true
);
attachmentMimeType = 'image/webp';
} catch {
throw new ImageFormatNotSupported({ format: detectedMime });
}
}
const filename = createHash('sha256')
.update(attachmentBuffer)
.digest('base64url');
const attachment = await this.storage.put(
userId,
session.config.workspaceId,
filename,
attachmentBuffer
);
attachments.push({
kind: 'url',
url: attachment,
mimeType: attachmentMimeType,
fileName: blob.filename,
});View on GitHub (pinned to b4c8548c09)
Solutions
- Re-encode the image client-side to standard JPEG/PNG/WebP before upload
- Verify the file opens in an image viewer and is not truncated (check byte size > 0 and matches source)
- Retry the upload — transient read/truncation during transfer can corrupt the buffer
- If maintaining this code: narrow the catch to decoder-specific errors and let unexpected failures surface separately
Example fix
// before
await inbox.createMessage(userId, { sessionId, blob: corruptedBuffer });
// after
try {
const webp = await processImage(buffer, maxEdge, true);
await inbox.createMessage(userId, { sessionId, blob: webp, blobMimeType: 'image/webp' });
} catch {
showUserError('This image format is not supported. Please use PNG, JPEG or WebP.');
} Defensive patterns
Strategy: validation
Validate before calling
const sniffed = await imageType(buffer); // e.g. file-type
const SUPPORTED = ['image/jpeg', 'image/png', 'image/webp', 'image/gif'];
if (!sniffed || !SUPPORTED.includes(sniffed.mime)) {
return rejectUpload('Use PNG, JPEG, WebP or GIF');
}
const probe = await loadImage(buffer); // throws on truncated/unsupported bytes
if (buffer.length === 0) return rejectUpload('Empty file'); Type guard
const isDecodableImage = async (buf: Buffer): Promise<boolean> => {
try { await sharp(buf).metadata(); return true; } catch { return false; }
}; Try / catch
try {
await inbox.createMessage(userId, { sessionId, blob });
} catch (e) {
if (e.code === 'image_format_not_supported') {
notifyUser(`Unsupported image format: ${e.format ?? 'unknown'}. Re-encode as PNG/JPEG/WebP.`);
} else throw e;
} Prevention
- Client-side pre-encode uploads to a standard format and verify decodability before sending
- Check file size > 0 and matches the source after any transfer/compression step
- Surface the reported {format} to the user so they know which file failed
When it happens
Trigger: Uploading a truncated or corrupted image file; an image whose extension/sniffed MIME says image/* but whose codec is unsupported (e.g. HEIC mislabeled, TIFF with odd compression, 16-bit PNG edge cases); a zero-byte or text file renamed to .png so the sniffer misclassifies it.
Common situations: Paste/drag from clipboard produces partial buffer; client-side compression library emits nonstandard webp/jpeg; users rename files to bypass type checks.
Related errors
- image_format_not_supported
- blob_invalid
- copilot_prompt_invalid
- copilot_session_invalid_input
- too_many_request
AI-assisted analysis of toeverything/AFFiNE@b4c8548c09 (2026-08-18).
Data as JSON: /api/errors/c854f2eca5bdd7c2.
Report an issue: GitHub.