{"record":{"id":"7e19617fe4424c31","repo":"pentaho/pentaho-kettle","slug":"pluginregistry005","errorCode":"PLUGINREGISTRY005","errorMessage":"Illegal access to class","messagePattern":"Illegal access to class","errorType":"error_code","errorClass":"KettlePluginException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/pentaho/di/core/plugins/PluginRegistry.java","lineNumber":529,"sourceCode":"        Class<? extends T> cl;\n        if ( plugin.isNativePlugin() ) {\n          cl = (Class<? extends T>) Class.forName( className );\n        } else {\n          ClassLoader ucl = getClassLoader( plugin );\n\n          // Load the class.\n          cl = (Class<? extends T>) ucl.loadClass( className );\n        }\n\n        return cl.newInstance();\n      } catch ( ClassNotFoundException e ) {\n        throw new KettlePluginException( BaseMessages.getString(\n            PKG, \"PluginRegistry.RuntimeError.ClassNotFound.PLUGINREGISTRY003\" ), e );\n      } catch ( InstantiationException e ) {\n        throw new KettlePluginException( BaseMessages.getString(\n            PKG, \"PluginRegistry.RuntimeError.UnableToInstantiateClass.PLUGINREGISTRY004\" ), e );\n      } catch ( IllegalAccessException e ) {\n        throw new KettlePluginException( BaseMessages.getString(\n            PKG, \"PluginRegistry.RuntimeError.IllegalAccessToClass.PLUGINREGISTRY005\" ), e );\n      } catch ( Throwable e ) {\n        e.printStackTrace();\n        throw new KettlePluginException( BaseMessages.getString(\n            PKG, \"PluginRegistry.RuntimeError.UnExpectedErrorLoadingClass.PLUGINREGISTRY007\" ), e );\n      }\n    }\n  }\n\n  /**\n   * Add a PluginType to be managed by the registry\n   *\n   * @param type\n   */\n  public static void addPluginType( PluginTypeInterface type ) {\n    pluginTypes.add( type );\n  }\n","sourceCodeStart":511,"sourceCodeEnd":547,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/core/src/main/java/org/pentaho/di/core/plugins/PluginRegistry.java#L511-L547","documentation":"In loadClass, an IllegalAccessException from cl.newInstance() — the class or its no-arg constructor is not accessible to the registry's caller — is rethrown as KettlePluginException 'Illegal access to class' (PLUGINREGISTRY005). This is a Java access-modifier problem, not a classpath problem.","triggerScenarios":"cl.newInstance() throws IllegalAccessException because the plugin class or its constructor is private/protected/package-private, or the class is in a non-exported package (Java 9+ modules / sealed packages) relative to PluginRegistry's loader context.","commonSituations":"Plugin implementation class declared package-private or nested (non-public static class); constructor made private by a singleton pattern; strong encapsulation (JPMS) blocks reflective access after a JDK upgrade.","solutions":["Make the plugin class public and give it a public no-argument constructor.","Move nested plugin classes out to top-level public classes.","Remove private constructors on the class Kettle must instantiate (use init()/lifecycle hooks instead of singleton enforcement).","On JDK 9+, add the appropriate --add-opens/--add-exports or module exports so the package is accessible."],"exampleFix":"// before\nclass MyStepMeta extends BaseStepMeta { // package-private\n  private MyStepMeta() { }\n}\n\n// after\npublic class MyStepMeta extends BaseStepMeta {\n  public MyStepMeta() { }\n}","handlingStrategy":"validation","validationCode":"Class<?> cl = pluginClassLoader.loadClass(fqn);\nint mods = cl.getModifiers();\nif (!Modifier.isPublic(mods)) throw new IllegalStateException(\"Plugin class not public: \" + fqn);\nConstructor<?> ctor = cl.getDeclaredConstructor();\nif (!Modifier.isPublic(ctor.getModifiers())) throw new IllegalStateException(\"Constructor not public: \" + fqn);","typeGuard":"static boolean isPubliclyInstantiable(Class<?> c) {\n  try {\n    return Modifier.isPublic(c.getModifiers())\n        && Modifier.isPublic(c.getDeclaredConstructor().getModifiers());\n  } catch (NoSuchMethodException e) { return false; }\n}","tryCatchPattern":"try {\n  return PluginRegistry.getInstance().loadClass(plugin, pluginClass);\n} catch (KettlePluginException e) {\n  if (e.getMessage().contains(\"Illegal access\")) {\n    log.error(\"Make plugin class and no-arg ctor public; check JPMS --add-opens on JDK 9+\", e);\n  }\n  throw e;\n}","preventionTips":["Declare plugin classes and constructors public; avoid package-private/nested implementations.","Don't enforce singletons via private constructors on classes Kettle instantiates.","After JDK upgrades, test plugin loading; add --add-opens for encapsulated packages.","Review access modifiers in code review for any class referenced in plugin metadata."],"tags":["kettle","plugins","reflection","access"],"backgroundTag":"permission-denied","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"}