karatelabs/karate · error · RuntimeException
latest image is not a valid image
Error message
latest image is not a valid image
What it means
ImageComparison's constructor decodes the latest image with ImageIO.read(); when the bytes decode to null (data is present but not a recognized image format such as PNG/JPEG/BMP/GIF), it throws this error. This is a data-content check, not a file-existence check: the bytes were found but are not decodable by the JDK's ImageIO.
Solutions
- Verify the latest file is a real PNG/JPEG (open it locally or check magic bytes with a hex dump)
- Re-take the screenshot; ensure the driver/browser was ready before capture
- Convert unsupported formats (WebP/SVG/AVIF) to PNG before diffing
- Check for git-lfs pointer files or truncated downloads; re-download the artifact
Example fix
// before
image.diff({ baseline: 'base.png', latest: 'shot.webp' }) // ImageIO cannot decode WebP
// after (convert first, e.g. via build tooling) then:
image.diff({ baseline: 'base.png', latest: 'shot.png' }) Defensive patterns
Strategy: validation
Validate before calling
// Pre-check the latest image is a real PNG/JPEG by magic bytes
byte[] b = karate.readBytes('latest.png');
boolean png = b.length > 8 && (b[0]&0xFF)==0x89 && b[1]=='P';
if (!png) throw new RuntimeException("latest.png is not a valid PNG"); Try / catch
try {
image.diff({ baseline: 'base.png', latest: 'latest.png' });
} catch (Exception e) {
if (String.valueOf(e).contains("not a valid image")) {
// log bytes length / re-capture screenshot and retry once
}
} Prevention
- Verify screenshots render locally before committing/using them
- Avoid WebP/SVG/AVIF; stick to PNG for baselines and latest
- Watch for git-lfs pointer files and truncated CI artifacts
- Add a capture-step assertion that the screenshot file is non-empty
When it happens
Trigger: latest bytes exist but are not a valid image: empty file (0 bytes is caught as null read), corrupted/truncated download, HTML error page saved as .png, SVG (not supported by ImageIO), WebP/AVIF (unsupported by most JDKs), or a text placeholder written where a screenshot was expected.
Common situations: Screenshot step silently captured a blank/failed driver page; CI artifact download produced an error page; a WebP or SVG file passed where PNG was expected; image truncated by an incomplete file copy or git-lfs pointer file not materialized.
Related errors
- baseline image is not a valid image
- image.diff: 'latest' image (bytes or path) is required
- image: unsupported image value
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/12a83223f599f2b2.
Report an issue: GitHub.
Appendix: source
Thrown at karate-image/src/main/java/io/karatelabs/ext/image/ImageComparison.java:111
private final Map<String, Object> options;
private final Map<String, Object> result;
private ImageComparison(
byte[] baselineImg, byte[] latestImg, Map<String, Object> options, Map<String, Object> defaultOptions) {
this.options = options;
this.result = new HashMap<>();
this.configure(defaultOptions);
this.baselineMissing = baselineImg == null || baselineImg.length == 0;
BufferedImage baselineImage;
BufferedImage latestImage;
try {
latestImage = ImageIO.read(new ByteArrayInputStream(latestImg));
if (latestImage == null) {
throw new RuntimeException("latest image is not a valid image");
}
baselineImage = baselineMissing ? latestImage : ImageIO.read(new ByteArrayInputStream(baselineImg));
if (baselineImage == null) {
throw new RuntimeException("baseline image is not a valid image");
}
} catch (IOException e) {
logger.error("image comparison failed while reading images: {}", e.getMessage());
throw new RuntimeException(e);
}
this.height = baselineImage.getHeight();
this.width = baselineImage.getWidth();
int latestHeight = latestImage.getHeight();
int latestWidth = latestImage.getWidth();
if (width != latestWidth || height != latestHeight) {View on GitHub (pinned to a22eb90246)