pentaho/pentaho-kettle · error · KettleException

JobEntryEvalTableContent.UnableSaveRep

Error message

JobEntryEvalTableContent.UnableSaveRep

What it means

JobEntryEvalTableContent.saveRep() writes this entry's settings (custom_sql, is_custom_sql, is_usevars, add_rows_result, clear_result_rows) to the repository; a KettleDatabaseException is rethrown as a KettleException with localized message 'JobEntryEvalTableContent.UnableSaveRep' plus the job id. Saving the job fails at this entry's attribute persistence step.

Solutions

  1. Inspect the chained KettleDatabaseException for the underlying SQL error.
  2. Verify the repository DB is writable, reachable, and has adequate space; review r_jobentry_attribute column limits for custom_sql.
  3. Ensure the entry has a valid ObjectId and the repository schema is up to date.
  4. Retry the save after connectivity/permission issues are fixed.
Defensive patterns

Strategy: try-catch

Validate before calling

if (jobMeta.getObjectId() == null) {
  throw new IllegalStateException("Job needs an id before saveRep");
}
if (!rep.connect()) {
  throw new IllegalStateException("Repository not reachable");
}

Try / catch

try {
  jobMeta.save();
} catch (KettleException e) {
  if (e.getCause() instanceof KettleDatabaseException) {
    logError("EvalTableContent save failed: " + e.getMessage(), e);
  }
  throw e;
}

Prevention

When it happens

Trigger: Saving a job to a repository where any rep.saveJobEntryAttribute(id_job, getObjectId(), ...) call inside the try block throws KettleDatabaseException.

Common situations: Repository database read-only, full, or disconnected mid-save; null ObjectId on the entry; column size exceeded by custom_sql; unmigrated repository schema.

Related errors


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

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/job/entries/evaluatetablecontent/JobEntryEvalTableContent.java:266

    return 0;
  }

  public void saveRep( Repository rep, IMetaStore metaStore, ObjectId id_job ) throws KettleException {
    try {
      rep.saveDatabaseMetaJobEntryAttribute( id_job, getObjectId(), "connection", "id_database", connection );

      rep.saveJobEntryAttribute( id_job, getObjectId(), "schemaname", schemaname );
      rep.saveJobEntryAttribute( id_job, getObjectId(), "tablename", tablename );
      rep.saveJobEntryAttribute(
        id_job, getObjectId(), "success_condition", getSuccessConditionCode( successCondition ) );
      rep.saveJobEntryAttribute( id_job, getObjectId(), "limit", limit );
      rep.saveJobEntryAttribute( id_job, getObjectId(), "custom_sql", customSQL );
      rep.saveJobEntryAttribute( id_job, getObjectId(), "is_custom_sql", useCustomSQL );
      rep.saveJobEntryAttribute( id_job, getObjectId(), "is_usevars", useVars );
      rep.saveJobEntryAttribute( id_job, getObjectId(), "add_rows_result", addRowsResult );
      rep.saveJobEntryAttribute( id_job, getObjectId(), "clear_result_rows", clearResultList );
    } catch ( KettleDatabaseException dbe ) {
      throw new KettleException( BaseMessages.getString( PKG, "JobEntryEvalTableContent.UnableSaveRep", ""
        + id_job ), dbe );
    }
  }

  public void setDatabase( DatabaseMeta database ) {
    this.connection = database;
  }

  public DatabaseMeta getDatabase() {
    return connection;
  }

  public boolean evaluates() {
    return true;
  }

  public boolean isUnconditional() {
    return false;

View on GitHub (pinned to f3058517a1)