{"record":{"id":"f3dfea7961f9cf41","repo":"pentaho/pentaho-kettle","slug":"unable-to-find-file-imagefile-for-plugin-plugin","errorCode":null,"errorMessage":"Unable to find file: <imageFile> for plugin: <plugin>","messagePattern":"Unable to find file: <imageFile> for plugin: <plugin>","errorType":"exception","errorClass":"KettleException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/core/gui/SwingGUIResource.java","lineNumber":188,"sourceCode":"            // Ignore, throws error below\n          }\n        }\n        if ( inputStream != null ) {\n          try {\n            BufferedImage bitmap = ImageIO.read( inputStream );\n\n            WaitingImageObserver wia = new WaitingImageObserver( bitmap );\n            wia.waitImageLoaded();\n\n            image = new SwingUniversalImageBitmap( bitmap );\n          } finally {\n            IOUtils.closeQuietly( inputStream );\n          }\n        }\n      }\n\n      if ( image == null ) {\n        throw new KettleException( \"Unable to find file: \" + plugin.getImageFile() + \" for plugin: \" + plugin );\n      }\n\n      return image;\n    } catch ( Throwable e ) {\n      throw new KettleException( \"Unable to load image from file : '\"\n        + plugin.getImageFile() + \"' for plugin: \" + plugin, e );\n    }\n  }\n\n  public Map<String, SwingUniversalImage> getEntryImages() {\n    return entryImages;\n  }\n\n  public Map<String, SwingUniversalImage> getStepImages() {\n    return stepImages;\n  }\n}\n","sourceCodeStart":170,"sourceCodeEnd":206,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/core/gui/SwingGUIResource.java#L170-L206","documentation":"getUniversalImageIcon throws this when, after trying to load the plugin's image from the classpath and filesystem locations, no SwingUniversalImage could be created. It is the 'icon resource not found' signal for plugin images in the Swing GUI.","triggerScenarios":"Calling SwingGUIResource image loading for a plugin whose getImageFile() points to a resource that cannot be opened via any registered ClassLoader or file path; inputStream is null for every candidate location.","commonSituations":"Plugin installed in a directory whose images subfolder is missing; jar built with resource filtering/exclusion; wrong relative path casing on case-sensitive filesystems.","solutions":["Open the plugin jar and confirm the image file exists at the declared path","Correct the imageFile declaration in plugin.xml or the plugin annotation","Rebuild the plugin with resources included (check maven resource includes/excludes)","Ensure the plugin folder structure matches what Kettle expects (e.g. plugin/lib + images)"],"exampleFix":"// before\nimageFile = \"icons/stepX.png\"; // file never packaged\n// after\nimageFile = \"images/stepX.png\"; // packaged under src/main/resources/images","handlingStrategy":"validation","validationCode":"try (InputStream in = loader.getResourceAsStream(plugin.getImageFile())) {\n  if (in == null) throw new IllegalStateException(\"Image not on classpath: \" + plugin.getImageFile());\n}","typeGuard":null,"tryCatchPattern":"try { image = getUniversalImageIcon(plugin); }\ncatch (KettleException e) { log.warn(\"Fallback default icon for \" + plugin.getIds()[0]); image = defaultImage; }","preventionTips":["Use exact case-sensitive resource paths (Linux deployments)","Check maven resource filtering is not corrupting binary images","Test plugin installs in a clean Spoon instance before release"],"tags":["pentaho-kettle","gui","resources","plugin-loading"],"backgroundTag":"file-not-found","analyzedSha":"f3058517a153da500bf4551f46d79b91bf8ec552","analyzedAt":"2026-09-13T14:04:16.340Z","contentChangedAt":"2026-09-13T14:04:16.340Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}