deepseek-ai/deepseek-harness · error · AttachmentError
INVALID_IMAGE
INVALID_IMAGE
Error message
Unsupported or malformed image data.
What it means
The raster inspector admits only PNG, JPEG, WebP, and GIF — the store's declared mediaTypes (MEDIA_TYPES in image.ts). imageMetadata throws INVALID_IMAGE when sharp's header parse reports any other format (TIFF, AVIF, HEIC, SVG, BMP, ...) or no recognizable format at all. This is admission policy, not a decode failure: sharp may support the format; this store does not.
Source
Thrown at packages/attachment/attachment-local/src/image.ts:66
gif: 'image/gif',
}
function carriesRetainedMetadata(metadata: Awaited<ReturnType<Sharp['metadata']>>): boolean {
return metadata.exif !== undefined
|| metadata.xmp !== undefined
|| metadata.iptc !== undefined
|| metadata.icc !== undefined
|| metadata.hasProfile
|| metadata.tifftagPhotoshop !== undefined
|| metadata.comments !== undefined
|| metadata.orientation !== undefined
}
async function imageMetadata(image: Sharp): Promise<DetectedImage> {
const metadata = await image.metadata()
const mediaType = MEDIA_TYPES[metadata.format as string]
if (mediaType === undefined) {
throw new AttachmentError('Unsupported or malformed image data.', 'INVALID_IMAGE')
}
// EXIF orientations 5-8 transpose the stored raster; report the perceived
// axes so limits, source facts, and coordinate advice all share them.
const transposed = metadata.orientation !== undefined && metadata.orientation >= 5
return {
mediaType,
width: transposed ? metadata.height : metadata.width,
height: transposed ? metadata.width : metadata.height,
animated: (metadata.pages ?? 1) > 1,
carriesMetadata: carriesRetainedMetadata(metadata),
depth: metadata.depth,
space: metadata.space,
hasAlpha: metadata.hasAlpha,
}
}
/**
* Parse a supported raster's header and return its intrinsic metadata withoutView on GitHub (pinned to b150a551b8)
Solutions
- Convert the image to a supported format before submitting: sharp(input).png().toBuffer() externally, or sips/ImageMagick on the client.
- Reject unsupported uploads client-side by checking the declared media type or magic bytes against the four supported formats.
- If the deployment genuinely needs another raster format, that requires changing MEDIA_TYPES in this package — there is no config field; request it upstream instead of catching and retrying.
Example fix
// before const detected = await detectImage(heicBytes) // after const detected = await detectImage(await sharp(heicBytes).png().toBuffer())
Defensive patterns
Strategy: validation
Validate before calling
const isSupportedImage = (b: Uint8Array): boolean =>
(b[0] === 0x89 && b[1] === 0x50) // PNG
|| (b[0] === 0xff && b[1] === 0xd8 && b[2] === 0xff) // JPEG
|| (b[0] === 0x47 && b[1] === 0x49 && b[2] === 0x46) // GIF
|| (b[0] === 0x52 && b[1] === 0x49 && b[8] === 0x57 && b[9] === 0x45) // RIFF....WEBP
if (!isSupportedImage(bytes)) throw new Error('convert to PNG/JPEG/WebP/GIF first') Type guard
import { isImageAdmissionError } from '@deepseek-ai/dsh-attachment'
const isInvalidImage = (e: unknown): boolean =>
isImageAdmissionError(e) && e.code === 'INVALID_IMAGE' Try / catch
try {
await store.saveImage(input)
} catch (error) {
if (isImageAdmissionError(error) && error.code === 'INVALID_IMAGE') {
// ask the sender to convert to PNG/JPEG/WebP/GIF; not retryable as-is
}
throw error
} Prevention
- Limit upload accept attributes and dropzones to the four supported media types.
- Convert HEIC/TIFF/AVIF at the ingestion edge before images enter the store.
- Validate magic bytes, not file extensions.
When it happens
Trigger: Calling probeImage or detectImage (including the store's validateImage / saveImages admission path) with bytes whose container format falls outside {png, jpeg, webp, gif}: HEIC phone photos, TIFF scans, SVGs, AVIF/JXL files, or non-image bytes that still yield a parsable sharp format string.
Common situations: iPhone HEIC/HEIF screenshots and camera uploads; scanner or fax TIFF output; SVG assets sent as images; files renamed to .png without conversion; a producer pipeline switching its default encoder to AVIF.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
AI-assisted analysis of deepseek-ai/deepseek-harness@b150a551b8 (2026-08-24).
Data as JSON: /api/errors/e0e6b43fe8c6a57e.
Report an issue: GitHub.