{"record":{"id":"5353f156f608112a","repo":"pentaho/pentaho-kettle","slug":"unable-to-find-thread-with-name-stepname-and-copy-number","errorCode":null,"errorMessage":"Unable to find thread with name ${stepname} and copy number ${copynr}","messagePattern":"Unable to find thread with name (.+?) and copy number (.+?)","errorType":"exception","errorClass":"KettleException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/trans/Trans.java","lineNumber":3457,"sourceCode":"  public boolean isSafeModeEnabled() {\n    return safeModeEnabled;\n  }\n\n  /**\n   * This adds a row producer to the transformation that just got set up. It is preferable to run this BEFORE execute()\n   * but after prepareExecution()\n   *\n   * @param stepname The step to produce rows for\n   * @param copynr   The copynr of the step to produce row for (normally 0 unless you have multiple copies running)\n   * @return the row producer\n   * @throws KettleException in case the thread/step to produce rows for could not be found.\n   * @see Trans#execute(String[])\n   * @see Trans#prepareExecution(String[])\n   */\n  public RowProducer addRowProducer( String stepname, int copynr ) throws KettleException {\n    StepInterface stepInterface = getStepInterface( stepname, copynr );\n    if ( stepInterface == null ) {\n      throw new KettleException( \"Unable to find thread with name \" + stepname + \" and copy number \" + copynr );\n    }\n\n    // We are going to add an extra RowSet to this stepInterface.\n    RowSet rowSet;\n    switch ( transMeta.getTransformationType() ) {\n      case Normal:\n        rowSet = new BlockingRowSet( transMeta.getSizeRowset() );\n        break;\n      case SerialSingleThreaded:\n        rowSet = new SingleRowRowSet();\n        break;\n      case SingleThreaded:\n        rowSet = new QueueRowSet();\n        break;\n      default:\n        throw new KettleException( \"Unhandled transformation type: \" + transMeta.getTransformationType() );\n    }\n","sourceCodeStart":3439,"sourceCodeEnd":3475,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/trans/Trans.java#L3439-L3475","documentation":"Trans.addRowProducer(stepname, copynr) injects rows into an already-prepared transformation step, but first looks up the step's thread. If no running step thread matches the given name and copy number, it throws this KettleException.","triggerScenarios":"Calling addRowProducer with a step name that doesn't exist in the transformation, a wrong copynr for a multi-copy step, or calling it before prepareExecution()/execute() so threads aren't registered yet.","commonSituations":"Typo in step name (names are case-sensitive), forgetting that clustered/split transformations run per-slave copies, invoking addRowProducer on a transformation not yet prepared.","solutions":["Ensure prepareExecution() (or execute()) was called before addRowProducer","Verify the step name exactly matches the step's name in the transformation (case-sensitive) and the copynr is within its cop ies count","Print available steps: iterate transMeta.getSteps() to confirm the name/copy you pass","For transformations loaded from a repository, use the step name as stored, not a renamed label"],"exampleFix":"// before\ntrans.prepareExecution(new String[0]);\nRowProducer rp = trans.addRowProducer(\"Inpu t\", 0); // typo\n// after\nRowProducer rp = trans.addRowProducer(\"Input\", 0);","handlingStrategy":"validation","validationCode":"// verify the step exists before calling addRowProducer\nboolean found = transMeta.getSteps().stream()\n  .anyMatch(sm -> sm.getName().equals(stepName) && sm.getCopies(transMeta) > copyNr);\nif (!found) throw new IllegalArgumentException(\"No such step: \" + stepName + \"#\" + copyNr);\n// and ensure threads exist\ntrans.prepareExecution(new String[0]);","typeGuard":null,"tryCatchPattern":"try {\n  RowProducer rp = trans.addRowProducer(stepName, copyNr);\n} catch (KettleException e) {\n  if (e.getMessage().startsWith(\"Unable to find thread\")) {\n    throw new IllegalArgumentException(\"Step/copy not running: \" + stepName + \"/\" + copyNr, e);\n  } else { throw e; }\n}","preventionTips":["Always call prepareExecution() before addRowProducer","Step names are case-sensitive — copy the exact name from the transformation","For steps with multiple copies, remember copynr is 0-based","Do not rename steps programmatically after prepareExecution but before addRowProducer"],"tags":["transformation","row-injection","invalid-argument"],"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"}