{"record":{"id":"784321d3a7cc1d91","repo":"pentaho/pentaho-kettle","slug":"the-simple-mapping-step-needs-one-mapping-output-step-to","errorCode":null,"errorMessage":"The simple mapping step needs one Mapping Output step to read from in the sub-transformation","messagePattern":"The simple mapping step needs one Mapping Output step to read from in the sub-transformation","errorType":"exception","errorClass":"KettleException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/trans/steps/simplemapping/SimpleMapping.java","lineNumber":197,"sourceCode":"    if ( mappingInputs.length == 0 ) {\n      throw new KettleException(\n        \"The simple mapping step needs one Mapping Input step to write to in the sub-transformation\" );\n    }\n    if ( mappingInputs.length > 1 ) {\n      throw new KettleException(\n        \"The simple mapping step does not support multiple Mapping Input steps to write to in the sub-transformation\" );\n    }\n    simpleMappingData.mappingInput = mappingInputs[0];\n    simpleMappingData.mappingInput.setConnectorSteps( new StepInterface[0], new ArrayList<MappingValueRename>(), null );\n\n    // LogTableField readField = data.mappingTransMeta.getTransLogTable().findField(TransLogTable.ID.LINES_READ);\n    // if (readField.getSubject() == null) {\n    // readField.setSubject(data.mappingInput.getStepMeta());\n    // }\n\n    MappingOutput[] mappingOutputs = simpleMappingData.mappingTrans.findMappingOutput();\n    if ( mappingOutputs.length == 0 ) {\n      throw new KettleException(\n          \"The simple mapping step needs one Mapping Output step to read from in the sub-transformation\" );\n    }\n    if ( mappingOutputs.length > 1 ) {\n      throw new KettleException( \"The simple mapping step does not support \"\n          + \"multiple Mapping Output steps to read from in the sub-transformation\" );\n    }\n    simpleMappingData.mappingOutput = mappingOutputs[0];\n\n    // LogTableField writeField = data.mappingTransMeta.getTransLogTable().findField(TransLogTable.ID.LINES_WRITTEN);\n    // if (writeField.getSubject() == null && data.mappingOutputs != null && data.mappingOutputs.length >= 1) {\n    // writeField.setSubject(data.mappingOutputs[0].getStepMeta());\n    // }\n\n    // Finally, add the mapping transformation to the active sub-transformations\n    // map in the parent transformation\n    //\n    getTrans().addActiveSubTransformation( getStepname(), simpleMappingData.mappingTrans );\n  }","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/trans/steps/simplemapping/SimpleMapping.java#L179-L215","documentation":"The Simple Mapping step executes a sub-transformation and pipes rows through a Mapping Input step into the sub-transformation and out through a Mapping Output step. During prepareMappingExecution, findMappingOutput() scans the sub-transformation for Mapping Output steps; if none exist there is no step to read resulting rows from, so a KettleException is thrown.","triggerScenarios":"SimpleMapping.prepareMappingExecution() (invoked from step init()) calls simpleMappingData.mappingTrans.findMappingOutput() and gets a zero-length array because the referenced sub-transformation contains no Mapping Output step.","commonSituations":"Developer points the Simple Mapping step at a sub-transformation that was built without a Mapping Output step (e.g. a normal transformation reused as a mapping, or the sub-transformation was edited and the Mapping Output step deleted), or the wrong transformation file/repository entry is referenced so the loaded sub-trans is not the intended mapping.","solutions":["Open the sub-transformation referenced by the Simple Mapping step and add a Mapping Output step, connecting it to the rest of the sub-transformation's stream.","Verify the mapping transformation reference (file name / repository directory + entry) points at the intended mapping, not a different transformation.","If multiple Mapping Output steps exist by mistake, remove all but one (SimpleMapping supports exactly one).","Ensure the sub-transformation is saved and re-loaded after edits so findMappingOutput() sees the current step set."],"exampleFix":"// Sub-transformation wrong: rows go to a normal 'Table output' step with no mapping output\n// Fix: add a 'Mapping output' step and wire the sub-transformation stream into it\n//   ... -> Mapping output\n// then in the parent transformation's Simple Mapping step, keep the reference to that sub-transformation","handlingStrategy":"validation","validationCode":"// Before running, verify the mapping sub-transformation has exactly one Mapping Output step\nTransMeta mappingTransMeta = new TransMeta(mappingFilePath);\nMappingOutput[] outputs = new MappingTransMeta(mappingTransMeta, null).findMappingOutput();\nif (outputs == null || outputs.length == 0) {\n  throw new IllegalStateException(\"Mapping sub-transformation '\" + mappingFilePath + \"' has no Mapping Output step\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  step.init(beforeExecutionData); // SimpleMapping init\n} catch (KettleException e) {\n  logError(\"Sub-transformation is missing its Mapping Output step: \" + e.getMessage());\n  return false; // fail fast with a clear configuration message\n}","preventionTips":["Always create mapping sub-transformations from the Mapping template so a Mapping Output step exists by default","Review sub-transformations in CI: assert exactly one Mapping Input and one Mapping Output step per mapping","Never delete the Mapping Output step when editing a mapping's downstream logic"],"tags":["kettle","pdi","sub-transformation","mapping-step","configuration"],"backgroundTag":"resource-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"}