pentaho/pentaho-kettle · error · KettleStepException

TransMeta.Exception.OneMappingOutputStepRequired

Error message

TransMeta.Exception.OneMappingOutputStepRequired

What it means

TransMeta.findMappingOutputStep() requires the transformation metadata to contain exactly one step of type MappingOutput; it throws KettleStepException with the 'OneMappingOutputStepRequired' key when no such step exists. Mapping (sub-)transformations need a MappingOutput step to feed results back to the parent transformation.

Solutions

  1. Open the sub-transformation used as the mapping and add a 'Mapping Output' step connected to the transformation's output flow.
  2. Verify the mappingFileName/transformation reference in the parent's Mapping step points to the intended sub-transformation, not the parent itself.
  3. If building TransMeta in code, add a StepMeta whose plugin/step is org.pentaho.di.trans.steps.mappingoutput.MappingOutput and addStep it before running.
  4. Re-export or re-import the mapping from the repository if the saved XML lost the step.

Example fix

// before: sub-transformation has only Text File Input -> (nothing)
// after: connect Text File Input -> Mapping Output step in the mapping transformation
// code equivalent:
// StepMeta mappingOutput = new StepMeta("MappingOutput",
//   new MappingOutputMeta());
// mappingOutput.setLocation(100, 100);
// transMeta.addStep(mappingOutput);
// transMeta.addTransHop(new TransHopMeta(textInput, mappingOutput));
Defensive patterns

Strategy: validation

Validate before calling

boolean ok = transMeta.getSteps().stream()
  .anyMatch(s -> s.getStepMetaInterface() instanceof MappingOutputMeta);
if (!ok) throw new IllegalStateException("Mapping sub-transformation needs exactly one Mapping Output step");

Type guard

boolean hasMappingOutput = transMeta.getSteps() != null
  && transMeta.getSteps().stream()
       .anyMatch(s -> s.getStepMetaInterface() instanceof MappingOutputMeta);

Try / catch

try {
  StepMeta out = transMeta.findMappingOutputStep();
} catch (KettleStepException e) {
  // add/re-add a MappingOutput step, then retry
}

Prevention

When it happens

Trigger: Calling TransMeta.findMappingOutputStep() (via mapping step execution, e.g. when a parent transformation runs a Mapping step) on a TransMeta whose step list contains zero MappingOutput steps.

Common situations: A user builds or loads a mapping transformation and forgets to add a 'Mapping Output' step; a mapping XML/S repository export was edited or truncated and the MappingOutput step was lost; programmatically assembling a sub-transformation for the Mapping step type without adding the output step.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13). Data as JSON: /api/errors/d7ee5f6d86e269e4. Report an issue: GitHub.

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/trans/TransMeta.java:6170

        throw new KettleStepException( BaseMessages.getString(
          PKG, "TransMeta.Exception.StepNameNotFound", stepname ) );
      }
      return stepMeta;
    } else {
      // Find the first mapping output step that fits the bill.
      StepMeta stepMeta = null;
      for ( StepMeta mappingStep : steps ) {
        if ( mappingStep.getStepID().equals( "MappingOutput" ) ) {
          if ( stepMeta == null ) {
            stepMeta = mappingStep;
          } else if ( stepMeta != null ) {
            throw new KettleStepException( BaseMessages.getString(
              PKG, "TransMeta.Exception.OnlyOneMappingOutputStepAllowed", "2" ) );
          }
        }
      }
      if ( stepMeta == null ) {
        throw new KettleStepException( BaseMessages.getString(
          PKG, "TransMeta.Exception.OneMappingOutputStepRequired" ) );
      }
      return stepMeta;
    }
  }

  /**
   * Gets a list of the resource dependencies.
   *
   * @return a list of ResourceReferences
   */
  public List<ResourceReference> getResourceDependencies() {
    return steps.stream()
      .flatMap( (StepMeta stepMeta) -> stepMeta.getResourceDependencies( this ).stream() )
      .collect( Collectors.toList() );
  }

  /**

View on GitHub (pinned to f3058517a1)