{"record":{"id":"7a416b31e4d801d1","repo":"pentaho/pentaho-kettle","slug":"no-setter-defined-for-rootclass","errorCode":null,"errorMessage":"No setter defined for <rootClass>","messagePattern":"No setter defined for <rootClass>","errorType":"exception","errorClass":"KettleException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/core/injection/bean/BeanInjector.java","lineNumber":260,"sourceCode":"              next = createObject( s.leafClass, root );\n              existList.set( index, next );\n            }\n            obj = next;\n            break;\n          case NONE:\n            // plain field\n            if ( s.field != null ) {\n              next = s.field.get( obj );\n              if ( next == null ) {\n                next = createObject( s.leafClass, root );\n                s.field.set( obj, next );\n              }\n              obj = next;\n            } else if ( s.getter != null ) {\n              next = s.getter.invoke( obj );\n              if ( next == null ) {\n                if ( s.setter == null ) {\n                  throw new KettleException( \"No setter defined for \" + root.getClass() );\n                }\n                next = s.leafClass.newInstance();\n                s.setter.invoke( obj, next );\n              }\n              obj = next;\n            } else {\n              throw new KettleException( \"No field or getter defined for \" + root.getClass() );\n            }\n            break;\n        }\n      } else {\n        // set to latest field\n        if ( !s.convertEmpty ) {\n          if ( data != null ) {\n            if ( data.isEmptyValue( dataName ) ) {\n              return true;\n            }\n          } else {","sourceCodeStart":242,"sourceCodeEnd":278,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/core/injection/bean/BeanInjector.java#L242-L278","documentation":"While walking an injection property path, the engine needed to instantiate an intermediate (non-leaf) object whose current value is null; if that path level has only a getter and no setter, the object cannot be assigned, so KettleException('No setter defined for <class>') is thrown.","triggerScenarios":"A property path passes through a nested bean whose getter returns null and which lacks a setter (e.g. getOptions() returns null with no setOptions), forcing the injector to create-and-assign a new instance — impossible without a setter.","commonSituations":"Plugin classes exposing read-only nested objects; step class refactored to drop setters; injection into fields that are only initialized lazily by the plugin's own init().","solutions":["Initialize the nested object before injection (call the step's init/defaults so the getter is non-null)","Add a setter to the intermediate class so the injector can install a new instance","Ensure the plugin class implements the expected bean-injection conventions (getters plus setters for nested injectable beans)"],"exampleFix":"// before\npublic Options getOptions() { return options; } // options==null, no setter\n// after\npublic Options getOptions() { return options = options != null ? options : new Options(); }\npublic void setOptions(Options o) { this.options = o; }","handlingStrategy":"try-catch","validationCode":"// ensure intermediate objects exist before injection\nif (meta.getNestedOptions() == null) meta.setNestedOptions(new NestedOptions());","typeGuard":null,"tryCatchPattern":"try { injector.setProperty(root, propName, data, n); }\ncatch (KettleException e) { throw new IllegalStateException(\"Path object not settable for \" + propName + \": \" + e.getMessage(), e); }","preventionTips":["Give every injectable nested bean both a getter and a setter","Call the metadata class's defaults/setDefault() before injection","Review plugin classes for lazy-null fields reachable by injection paths"],"tags":["pentaho-kettle","metadata-injection","reflection","null"],"backgroundTag":"missing-dependency","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"}