pentaho/pentaho-kettle · error · KettleException

Unable to find image file

Error message

Unable to find image file: <imageFile> for plugin: <plugin>

What it means

Thrown by SwingGUIResource.loadEntryImages when the plugin registry reports an image file for a job/plugin entry but SwingGUIResource.getUniversalImageIcon cannot resolve it to a SwingUniversalImage (returned null). Pentaho Kettle loads all entry/step icons at GUI startup into a map keyed by plugin id; a missing icon breaks GUI resource initialization.

Solutions

  1. Verify the imageFile path declared by the plugin exists on the classpath or inside the plugin jar/zip at the exact path
  2. Fix the plugin.xml image-file entry or @Injection/@Step metadata to point at the actual icon resource
  3. Rebuild/redeploy the plugin including its resources (icons often excluded by build filters)
  4. Clear the plugin cache folder and restart so stale plugin folders are re-scanned

Example fix

// before (plugin.xml)
<image-file>icons/wrng.png</image-file>
// after
<image-file>icons/wrong.png</image-file>
Defensive patterns

Strategy: validation

Validate before calling

String img = plugin.getImageFile();
if (img == null || getClass().getResourceAsStream(img) == null && !new java.io.File(img).exists()) {
  throw new IllegalStateException("Icon resource missing for plugin " + plugin.getIds()[0] + ": " + img);
}

Try / catch

try { SwingUniversalImage image = getUniversalImageIcon(plugin); }
catch (KettleException e) { log.logError("Skipping icon for " + plugin.getIds()[0], e); continue; }

Prevention

When it happens

Trigger: A plugin declares an imageFile in its plugin.xml/annotation that does not exist on the classpath or in the plugin's jar/folder, so getUniversalImageIcon returns null after exhausting all lookup locations.

Common situations: Hand-written plugin.xml with a typo in <image-file>; plugin jar repackaged without image resources; renamed/moved icon files after an upgrade; plugin folder copied without resource files.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13). Data as JSON: /api/errors/1440246c2fa6c793. Report an issue: GitHub.

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/core/gui/SwingGUIResource.java:91

          + plugin.getName() + " (id=" + plugin.getIds()[0] + ")", e );
      }
    }

    return map;
  }

  private Map<String, SwingUniversalImage> loadEntryImages() {
    Map<String, SwingUniversalImage> map = new HashMap<>();

    for ( PluginInterface plugin : PluginRegistry.getInstance().getPlugins( JobEntryPluginType.class ) ) {
      try {
        if ( JobMeta.STRING_SPECIAL.equals( plugin.getIds()[0] ) ) {
          continue;
        }

        SwingUniversalImage image = getUniversalImageIcon( plugin );
        if ( image == null ) {
          throw new KettleException( "Unable to find image file: "
            + plugin.getImageFile() + " for plugin: " + plugin );
        }

        map.put( plugin.getIds()[0], image );
      } catch ( Exception e ) {
        log.logError( "Unable to load job entry icon image for plugin: "
          + plugin.getName() + " (id=" + plugin.getIds()[0] + ")", e );
      }
    }

    return map;
  }

  private SwingUniversalImage getUniversalImageIcon( PluginInterface plugin ) throws KettleException {
    try {
      PluginRegistry registry = PluginRegistry.getInstance();
      String filename = plugin.getImageFile();

View on GitHub (pinned to f3058517a1)