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

  1. Run the JVM in headless mode (-Djava.awt.headless=true) on servers, or ensure a working DISPLAY/X server is available.
  2. Check the referenced transformation/job renders correctly in Spoon; fix its metadata if the diagram generation fails.
  3. Verify the JDK includes the standard PNG ImageWriter (ImageIO.getWriterFormatNames()).
  4. 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

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


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)