opendataloader-project/opendataloader-pdf · error · IOException
No ImageIO writer accepted PNG output for page %s
Error message
No ImageIO writer accepted PNG output for page %s
What it means
After fetching a page image, DiskPageImageCache persists it with ImageIO.write(image, "png", file). ImageIO.write returns false when no registered ImageWriter accepts the PNG format for that image type, which the cache treats as a fatal IOException because caching would silently produce nothing. It indicates the PNG writer plugin is unavailable in the runtime JRE.
Source
Thrown at java/opendataloader-pdf-core/src/main/java/org/opendataloader/pdf/hybrid/DiskPageImageCache.java:64
@Override
public BufferedImage getOrFetch(int pageIndex, PageImageFetcher fetcher) throws IOException {
Path file = tempDir.resolve("page-" + pageIndex + ".png");
if (Files.exists(file)) {
BufferedImage cached = ImageIO.read(file.toFile());
if (cached != null) {
return cached;
}
// Cached file is unreadable (corrupt or no ImageReader) — re-fetch.
LOGGER.log(Level.WARNING, "Cached page image is unreadable, re-fetching: {0}", file);
Files.deleteIfExists(file);
}
BufferedImage image = fetcher.fetch(pageIndex);
if (image == null) {
throw new IOException("Page image fetcher returned null for page " + pageIndex);
}
if (!ImageIO.write(image, "png", file.toFile())) {
throw new IOException("No ImageIO writer accepted PNG output for page " + pageIndex);
}
return image;
}
@Override
public void evict(int pageIndex) {
// no-op: keep on disk for potential re-read
}
@Override
public void close() throws IOException {
if (!Files.exists(tempDir)) {
return;
}
try (DirectoryStream<Path> stream = Files.newDirectoryStream(tempDir)) {
for (Path entry : stream) {
try {
Files.deleteIfExists(entry);View on GitHub (pinned to a7789b8e77)
Solutions
- Use a full JRE/JDK distribution (not a jlink-stripped runtime) so com.sun.imageio.plugins.png is present
- Verify PNG support at startup: ImageIO.getImageWritersByFormatName("png").hasNext()
- If packaging with jlink, include the java.desktop module
- Check for dependency shading that relocates/excludes imageio service files under META-INF/services
Defensive patterns
Strategy: validation
Validate before calling
// Verify PNG write support once at startup
boolean pngOk = javax.imageio.ImageIO.getImageWritersByFormatName("png").hasNext();
if (!pngOk) {
throw new IllegalStateException(
"No ImageIO PNG writer registered — use a full JRE/JDK, not a stripped runtime");
} Try / catch
try {
return cache.getOrFetch(pageIndex, fetcher);
} catch (IOException e) {
if (e.getMessage().contains("No ImageIO writer accepted PNG")) {
LOG.error("PNG ImageIO plugin missing from JRE — install java.desktop / full JDK", e);
}
throw e;
} Prevention
- Run on a full JDK, not a jlink-stripped runtime missing java.desktop
- Smoke-test ImageIO PNG writers in CI on the production image
- Watch for dependency shading that drops META-INF/services imageio entries
When it happens
Trigger: ImageIO.write returns false for the 'png' format — i.e. no ImageIO service provider for PNG is registered, or the BufferedImage type is one no writer will accept. The page index is included in the message.
Common situations: Running on a stripped/headless JRE or a minimal container image that omits the javax.imageio PNG plugins; shading/dependency conflicts that drop imageio plugins; custom BufferedImage subtypes with an unusual color model.
Related errors
- Unsupported hybrid backend '%s'. Supported values: %s
- Option --hybrid requires a value. Supported values: %s
- Unsupported hybrid backend '%s'. Supported values: %s
- Option --%s: unsupported value '%s'. Supported values: %s, %
- Option --%s: unsupported value '%s'. Supported values: %s, %
AI-assisted analysis of opendataloader-project/opendataloader-pdf@a7789b8e77 (2026-08-14).
Data as JSON: /api/errors/65c869bc1c135c33.
Report an issue: GitHub.