pentaho/pentaho-kettle · error · KettleException
Unable to serialize image to PNG
Error message
Unable to serialize image to PNG
What it means
AutoDoc.processRow throws KettleException 'Unable to serialize image to PNG' (hardcoded, no message key) when KettleFileTableModel.getImage returns a bad image or ImageIO.write fails, or when closing the ByteArrayOutputStream throws IOException. The step captures a diagram image for each subject into a PNG byte array for the output row.
Solutions
- Run the JVM in headless mode (-Djava.awt.headless=true) on servers, or ensure a working DISPLAY/X server is available.
- Check the referenced transformation/job renders correctly in Spoon; fix its metadata if the diagram generation fails.
- Verify the JDK includes the standard PNG ImageWriter (ImageIO.getWriterFormatNames()).
- Update Kettle to a version where image rendering for the subject type is supported.
Example fix
// before: java -jar kitchen.jar ... // after java -Djava.awt.headless=true -jar kitchen.jar ...
Defensive patterns
Strategy: try-catch
Validate before calling
// Check PNG writer and headless support before running
if (ImageIO.write(ImageIO.createImage(1, 1, BufferedImage.TYPE_INT_RGB).orElse(null), "png", new ByteArrayOutputStream()) == false &&
!ImageIO.getImageWritersByFormatName("png").hasNext()) {
throw new IllegalStateException("No PNG image writer available in this JVM");
} Type guard
public static boolean isRenderable(BufferedImage image) {
return image != null && image.getWidth() > 0 && image.getHeight() > 0;
} Try / catch
try {
BufferedImage image = KettleFileTableModel.getImage(bowl, location);
if (image == null) throw new IllegalStateException("No image for " + location);
ImageIO.write(image, "png", outputStream);
} catch (Exception e) {
logError("PNG serialization failed: " + e.getMessage(), e);
setErrors(1);
} Prevention
- Start the JVM with -Djava.awt.headless=true on servers.
- Verify diagrams render in Spoon for all subjects being documented.
- Confirm the JDK has standard ImageIO PNG support.
When it happens
Trigger: KettleFileTableModel.getImage returns null or throws (subject not renderable), ImageIO.write cannot encode the BufferedImage to PNG, or outputStream.close() throws IOException in the finally block.
Common situations: Headless servers without AWT graphics support (no DISPLAY / java.awt.headless issues); corrupt or unavailable transformation/job metadata preventing diagram rendering; JVM missing PNG image writer.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- AddSequenceMeta.Exception.ErrorLoadingStepInfo
- All input files need to have the same number of fields. File
- AnalyticQueryMeta.Exception.UnexpectedErrorInReadingStepInfo…
- AnalyticQueryMeta.Exception.UnableToLoadStepInfoFromXML
- AnalyticQueryMeta.Exception.UnableToSaveStepInfoToRepository
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/0e5b61798e48cc4a.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/core/impl/src/main/java/org/pentaho/di/trans/steps/autodoc/AutoDoc.java:286
if ( meta.isIncludingCreated() ) {
outputRow[outputIndex++] = KettleFileTableModel.getCreation( getTransMeta().getBowl(), location );
}
// modified
if ( meta.isIncludingModified() ) {
outputRow[outputIndex++] = KettleFileTableModel.getModification( getTransMeta().getBowl(), location );
}
// image
if ( meta.isIncludingImage() ) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try {
BufferedImage image = KettleFileTableModel.getImage( getTransMeta().getBowl(), location );
ImageIO.write( image, "png", outputStream );
outputRow[outputIndex++] = outputStream.toByteArray();
} catch ( Exception e ) {
throw new KettleException( "Unable to serialize image to PNG", e );
} finally {
try {
outputStream.close();
} catch ( IOException e ) {
throw new KettleException( "Unable to serialize image to PNG", e );
}
}
}
if ( meta.isIncludingLoggingConfiguration() ) {
outputRow[outputIndex++] = KettleFileTableModel.getLogging( getTransMeta().getBowl(), location );
}
if ( meta.isIncludingLastExecutionResult() ) {
outputRow[outputIndex++] = KettleFileTableModel.getLogging( getTransMeta().getBowl(), location );
}
if ( meta.isIncludingImageAreaList() ) {View on GitHub (pinned to f3058517a1)