{"record":{"id":"48d693e0e0a3e66b","repo":"pentaho/pentaho-kettle","slug":"you-can-not-get-metrics-for-the-target-step","errorCode":null,"errorMessage":"You can not get metrics for the target step [","messagePattern":"You can not get metrics for the target step \\[","errorType":"exception","errorClass":"KettleException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/trans/steps/stepsmetrics/StepsMetrics.java","lineNumber":96,"sourceCode":"      data.realsteplineswrittentfield = environmentSubstitute( meta.getStepLinesWrittenFieldName() );\n      data.realsteplinesupdatedfield = environmentSubstitute( meta.getStepLinesUpdatedFieldName() );\n      data.realsteplineserrorsfield = environmentSubstitute( meta.getStepLinesErrorsFieldName() );\n      data.realstepsecondsfield = environmentSubstitute( meta.getStepSecondsFieldName() );\n\n      // Get target stepnames\n      String[] targetSteps = getTransMeta().getNextStepNames( getStepMeta() );\n\n      data.stepInterfaces = new ConcurrentHashMap<Integer, StepInterface>();\n      for ( int i = 0; i < stepnrs; i++ ) {\n        // We can not get metrics from current step\n        if ( stepnames[i].equals( getStepname() ) ) {\n          throw new KettleException( \"You can not get metrics for the current step [\" + stepnames[i] + \"]!\" );\n        }\n        if ( targetSteps != null ) {\n          // We can not metrics from the target steps\n          for ( int j = 0; j < targetSteps.length; j++ ) {\n            if ( stepnames[i].equals( targetSteps[j] ) ) {\n              throw new KettleException( \"You can not get metrics for the target step [\" + targetSteps[j] + \"]!\" );\n            }\n          }\n        }\n\n        int CopyNr = Const.toInt( meta.getStepCopyNr()[i], 0 );\n        StepInterface si = getTrans().getStepInterface( stepnames[i], CopyNr );\n        if ( si != null ) {\n          data.stepInterfaces.put( i, getDispatcher().findBaseSteps( stepnames[i] ).get( CopyNr ) );\n        } else {\n          if ( meta.getStepRequired()[i].equals( StepsMetricsMeta.YES ) ) {\n            throw new KettleException( \"We cannot get step [\" + stepnames[i] + \"] CopyNr=\" + CopyNr + \"!\" );\n          }\n        }\n      }\n\n      data.outputRowMeta = new RowMeta();\n      meta.getFields( getTransMeta().getBowl(), data.outputRowMeta, getStepname(), null, null, this, repository,\n        metaStore );","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/trans/steps/stepsmetrics/StepsMetrics.java#L78-L114","documentation":"StepsMetrics refuses to sample metrics from a step that is a direct downstream target (hop successor) of the metrics step itself, because doing so would create a circular data dependency: the target step's execution depends on the metrics step completing. processRow throws this KettleException when a monitored name matches getTransMeta().getNextStepNames(getStepMeta()).","triggerScenarios":"The monitored-steps grid lists a step that is directly connected by a hop from the StepsMetrics step, discovered at processRow time by comparing stepnames[i] against targetSteps.","commonSituations":"Wiring the metrics step's output into a monitored step while also listing it in the grid; reusing a monitored-step name after rewiring hops; copying step configurations between transformations where hop topology differs.","solutions":["Remove the target step's name from the StepsMetrics monitored-steps grid.","Restructure hops so the metrics step is not feeding the steps it monitors (monitor upstream/sibling steps only).","If the step must be monitored, add a separate StepsMetrics instance whose output goes elsewhere.","Validate hop topology in the step dialog before running the transformation."],"exampleFix":"// before: monitoring a downstream hop target\n// hop: Metrics -> StreamLookup ; monitored list: [StreamLookup]\nmeta.setStepName(new String[] { \"StreamLookup\" });\n// after: monitor a step not downstream of Metrics\nmeta.setStepName(new String[] { \"Table input\", \"Sort rows\" });","handlingStrategy":"validation","validationCode":"java.util.List<String> targets = java.util.Arrays.asList(transMeta.getNextStepNames(metricsStepMeta));\nfor (String monitored : meta.getStepName()) {\n  if (targets.contains(monitored)) {\n    throw new IllegalArgumentException(\"StepsMetrics cannot monitor downstream target step: \" + monitored);\n  }\n}","typeGuard":"boolean noTargetOverlap(StepMeta metricsStep, TransMeta tm, StepsMetricsMeta m) {\n  String[] targets = tm.getNextStepNames(metricsStep);\n  if (targets == null) return true;\n  return java.util.Arrays.stream(m.getStepName()).noneMatch(n -> java.util.Arrays.asList(targets).contains(n));\n}","tryCatchPattern":"try {\n  trans.execute(null);\n} catch (KettleException e) {\n  if (e.getMessage().startsWith(\"You can not get metrics for the target step [\")) {\n    throw new IllegalStateException(\"StepsMetrics monitors one of its own hop targets\", e);\n  }\n  throw e;\n}","preventionTips":["Keep the StepsMetrics step's output hop disconnected from the steps it monitors.","Review hop topology whenever you edit the monitored-steps list.","Run a pre-execution metadata check that compares monitored names with downstream step names."],"tags":["configuration","cycle","steps-metrics"],"backgroundTag":"invalid-state-transition","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"}