{"record":{"id":"9517758b36f3359b","repo":"pentaho/pentaho-kettle","slug":"databasejoinmeta-exception-unabletosavestepinfo-id-step","errorCode":null,"errorMessage":"DatabaseJoinMeta.Exception.UnableToSaveStepInfo + id_step","messagePattern":"DatabaseJoinMeta\\.Exception\\.UnableToSaveStepInfo \\+ id_step","errorType":"exception","errorClass":"KettleException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/trans/steps/databasejoin/DatabaseJoinMeta.java","lineNumber":394,"sourceCode":"    try {\n      rep.saveDatabaseMetaStepAttribute( id_transformation, id_step, \"id_connection\", databaseMeta );\n      rep.saveStepAttribute( id_transformation, id_step, \"rowlimit\", rowLimit );\n      rep.saveStepAttribute( id_transformation, id_step, \"sql\", sql );\n      rep.saveStepAttribute( id_transformation, id_step, \"outer_join\", outerJoin );\n      rep.saveStepAttribute( id_transformation, id_step, \"replace_vars\", replacevars );\n\n      for ( int i = 0; i < parameterField.length; i++ ) {\n        rep.saveStepAttribute( id_transformation, id_step, i, \"parameter_field\", parameterField[i] );\n        rep.saveStepAttribute( id_transformation, id_step, i, \"parameter_type\", ValueMetaFactory\n            .getValueMetaName( parameterType[i] ) );\n      }\n\n      // Also, save the step-database relationship!\n      if ( databaseMeta != null ) {\n        rep.insertStepDatabase( id_transformation, id_step, databaseMeta.getObjectId() );\n      }\n    } catch ( Exception e ) {\n      throw new KettleException( BaseMessages.getString( PKG, \"DatabaseJoinMeta.Exception.UnableToSaveStepInfo\" )\n        + id_step, e );\n    }\n  }\n\n  @Override\n  public void check( List<CheckResultInterface> remarks, TransMeta transMeta, StepMeta stepMeta,\n    RowMetaInterface prev, String[] input, String[] output, RowMetaInterface info, VariableSpace space,\n    Repository repository, IMetaStore metaStore ) {\n\n    CheckResult cr;\n    String error_message = \"\";\n\n    if ( databaseMeta != null ) {\n      Database db = new Database( loggingObject, databaseMeta );\n      databases = new Database[] { db }; // Keep track of this one for cancelQuery\n\n      try {\n        db.connect();","sourceCodeStart":376,"sourceCodeEnd":412,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/trans/steps/databasejoin/DatabaseJoinMeta.java#L376-L412","documentation":"DatabaseJoinMeta.saveRep() wraps any exception thrown while persisting this step's attributes (or inserting the step-database relationship via rep.insertStepDatabase) into a KettleException whose message is 'Unable to save step info' + id_step. It exists so that repository write failures during transformation save carry the offending step id in the message.","triggerScenarios":"Calling saveRep() (directly or when saving a transformation to a repository) when any rep.saveStepAttribute* call, rep.insertStepDatabase, or ValueMetaFactory.getNameForValueMeta throws — e.g. read-only repository, lost connection mid-save, or databaseMeta set but its ObjectId is null.","commonSituations":"Saving a transformation while the repository DB connection was dropped; saving into a read-only user account; a DatabaseMeta that was built in memory and never stored, so getObjectId() is null.","solutions":["Read the nested cause to find the underlying repository/SQL error","Verify the repository user has write permission on the target partition","Ensure the associated DatabaseMeta has been saved (non-null ObjectId) before saving the step metadata","Reconnect/retry the repository save once the connection is healthy"],"exampleFix":"// before\nrep.insertStepDatabase( id_transformation, id_step, databaseMeta.getObjectId() );\n// after\nif ( databaseMeta != null ) {\n  if ( databaseMeta.getObjectId() == null ) {\n    rep.save( databaseMeta, id_transformation, metaStore );\n  }\n  rep.insertStepDatabase( id_transformation, id_step, databaseMeta.getObjectId() );\n}","handlingStrategy":"try-catch","validationCode":"// before saving a transformation\nif ( stepMeta.getDatabaseMeta() != null && stepMeta.getDatabaseMeta().getObjectId() == null ) {\n  rep.save( stepMeta.getDatabaseMeta(), transMeta.getObjectId(), metaStore );\n}\nif ( !rep.isConnected() ) throw new KettleException( \"Repository not connected\" );","typeGuard":null,"tryCatchPattern":"try {\n  transMeta.saveRep( rep, metaStore, transId );\n} catch ( KettleException e ) {\n  if ( e.getMessage() != null && e.getMessage().contains( \"Unable to save step info\" ) ) {\n    logError( \"Save failed at step \" + e.getMessage() + \"; cause=\" + e.getCause(), e );\n    // reconnect and retry once\n  } else { throw e; }\n}","preventionTips":["Save referenced DatabaseMetas before saving steps","Use a repository account with write privileges","Check repository connectivity/health before bulk saves","Inspect getCause() to find which attribute write failed"],"tags":["kettle","repository","serialization"],"backgroundTag":"database-write-failed","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"}