{"record":{"id":"c8b92c618f092a6d","repo":"pentaho/pentaho-kettle","slug":"pluginregistry006","errorCode":"PLUGINREGISTRY006","errorMessage":"Malformed URL","messagePattern":"Malformed URL","errorType":"error_code","errorClass":"KettlePluginException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/pentaho/di/core/plugins/PluginRegistry.java","lineNumber":996,"sourceCode":"                      }\n                    }\n                    ucl = createClassLoader( plugin );\n                    classLoaders.put( plugin, ucl ); // save for later use...\n                    inverseClassLoaderLookup.computeIfAbsent( ucl, k -> new HashSet<>() ).add( plugin );\n                  }\n                }\n              }\n            }\n          }\n        } finally {\n          lock.writeLock().unlock();\n        }\n\n        // Load the class.\n        return ucl;\n      }\n    } catch ( MalformedURLException e ) {\n      throw new KettlePluginException( BaseMessages.getString(\n          PKG, \"PluginRegistry.RuntimeError.MalformedURL.PLUGINREGISTRY006\" ), e );\n    } catch ( Throwable e ) {\n      e.printStackTrace();\n      throw new KettlePluginException( BaseMessages.getString(\n          PKG, \"PluginRegistry.RuntimeError.UnExpectedCreatingClassLoader.PLUGINREGISTRY008\" ), e );\n    }\n  }\n\n  /**\n   * Allows the tracking of plugins as they come and go.\n   *\n   * @param typeToTrack extension of PluginTypeInterface to track.\n   * @param listener    receives notification when a plugin of the specified type is added/removed/modified\n   * @param <T>         extension of PluginTypeInterface\n   */\n  public <T extends PluginTypeInterface> void addPluginListener( Class<T> typeToTrack, PluginTypeListener listener ) {\n    lock.writeLock().lock();\n    try {","sourceCodeStart":978,"sourceCodeEnd":1014,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/core/src/main/java/org/pentaho/di/core/plugins/PluginRegistry.java#L978-L1014","documentation":"KettlePluginException thrown by PluginRegistry.createClassLoader when constructing the URLClassLoader for a plugin fails because one of the plugin's jar/lib URLs is malformed. The registry converts each plugin folder/jar path into java.net.URL objects; an invalid URL string (bad syntax, unescaped characters, invalid protocol) triggers MalformedURLException which is wrapped with code PLUGINREGISTRY006.","triggerScenarios":"Calling PluginRegistry.createClassLoader (directly or via plugin initialization) when a plugin's jarFiles list or plugin folder yields a URL that java.net.URL cannot parse - e.g. a path with spaces or illegal characters not escaped, or an unsupported protocol scheme.","commonSituations":"Plugin installed in a directory whose name contains spaces or non-ASCII characters; manually configured plugin paths in kettle.properties or plugin.xml with typos; Windows-style paths passed as URLs; a plugin jar moved/deleted leaving a stale relative path.","solutions":["Fix the plugin path so it is a valid URL: escape spaces (%20) or use folder.toURI().toURL() instead of new URL(folderPath)","Check the plugin folder/jar actually exists and the path in the plugin configuration is correct","Move the plugin to a directory without spaces or special characters","Inspect the wrapped MalformedURLException cause for the exact offending URL"],"exampleFix":"// before\nURL url = new URL(\"file:/opt/pentaho/plugins/my plugin/lib/x.jar\");\n// after\nURL url = new File(\"/opt/pentaho/plugins/my plugin/lib/x.jar\").toURI().toURL();","handlingStrategy":"try-catch","validationCode":"String p = \"/opt/pentaho/plugins/my plugin\";\njava.io.File f = new java.io.File(p);\nif ( !f.exists() ) throw new IllegalStateException(\"plugin folder missing: \" + p);\njava.net.URL url = f.toURI().toURL(); // never throws MalformedURLException for existing files","typeGuard":"static boolean isSafePluginPath(String p) {\n  return p != null && !p.isEmpty() && new java.io.File(p).exists();\n}","tryCatchPattern":"try {\n  ClassLoader ucl = PluginRegistry.init().createClassLoader(plugin, null);\n} catch ( KettlePluginException e ) {\n  // e.getMessage() contains PLUGINREGISTRY006; getCause() is the MalformedURLException\n  log.error(\"Bad plugin URL for \" + plugin.getName() + \": \" + e.getCause().getMessage());\n}","preventionTips":["Use File.toURI().toURL() instead of new URL(pathString) for plugin locations","Avoid spaces/non-ASCII characters in plugin install directories","Validate plugin folder paths at startup before registering plugins","Log the resolved URLs of every plugin jar during deployment checks"],"tags":["java","classpath","plugin-system","url"],"backgroundTag":"invalid-url-format","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"}