{"record":{"id":"860839941938a59a","repo":"pentaho/pentaho-kettle","slug":"jobentrytruncatetables-unablesaverep","errorCode":null,"errorMessage":"JobEntryTruncateTables.UnableSaveRep","messagePattern":"JobEntryTruncateTables\\.UnableSaveRep","errorType":"exception","errorClass":"KettleException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/job/entries/truncatetables/JobEntryTruncateTables.java","lineNumber":180,"sourceCode":"      throw new KettleException( BaseMessages.getString( PKG, \"JobEntryTruncateTables.UnableLoadRep\", \"\"\n        + id_jobentry ), dbe );\n    }\n  }\n\n  public void saveRep( Repository rep, IMetaStore metaStore, ObjectId id_job ) throws KettleException {\n    try {\n      rep.saveDatabaseMetaJobEntryAttribute( id_job, getObjectId(), \"connection\", \"id_database\", connection );\n\n      rep.saveJobEntryAttribute( id_job, getObjectId(), \"arg_from_previous\", this.argFromPrevious );\n      // save the arguments...\n      if ( this.arguments != null ) {\n        for ( int i = 0; i < this.arguments.length; i++ ) {\n          rep.saveJobEntryAttribute( id_job, getObjectId(), i, \"name\", this.arguments[i] );\n          rep.saveJobEntryAttribute( id_job, getObjectId(), i, \"schemaname\", this.schemaname[i] );\n        }\n      }\n    } catch ( KettleDatabaseException dbe ) {\n      throw new KettleException(\n        BaseMessages.getString( PKG, \"JobEntryTruncateTables.UnableSaveRep\", \"\" + id_job ), dbe );\n    }\n  }\n\n  public void setDatabase( DatabaseMeta database ) {\n    this.connection = database;\n  }\n\n  public DatabaseMeta getDatabase() {\n    return this.connection;\n  }\n\n  public boolean evaluates() {\n    return true;\n  }\n\n  public boolean isUnconditional() {\n    return true;","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/job/entries/truncatetables/JobEntryTruncateTables.java#L162-L198","documentation":"JobEntryTruncateTables.saveRep() wraps a KettleDatabaseException from rep.saveJobEntryAttribute(...) into a KettleException with message 'JobEntryTruncateTables.UnableSaveRep' plus the id_job. It means the job entry's table list could not be written to the repository database.","triggerScenarios":"Calling saveRep(rep, metaStore, id_job) when the repository DB insert/update of the 'name'/'schemaname' attributes fails — connection loss, constraint violation, read-only schema, or null arguments/schemaname array entries on a repository that rejects them.","commonSituations":"Repository database read-only or out of space; network drop mid-save; concurrent edits causing lock timeouts; missing write privileges for the repository user.","solutions":["Check the repository database is writable and the user has INSERT/UPDATE rights on R_JOBENTRY_ATTRIBUTE.","Retry the save after confirming DB connectivity; inspect the cause for the exact SQL error.","Free up space / resolve lock contention on the repository tables.","If the repository is consistently failing, export the job to XML (.kjb) as a workaround and fix the DB."],"exampleFix":"// before: saving with a disconnected repository\nrep.saveRep(...); // fails silently earlier, then saveRep throws\n// after: check connection before saving\nif ( !rep.isConnected() ) { rep.connect(user, pass); }\nrep.saveRep(metaStore, id_job);","handlingStrategy":"try-catch","validationCode":"// Pre-flight checks before saveRep\nif ( !rep.isConnected() ) throw new KettleException(\"Repository not connected\");\nfor ( String arg : jobEntry.getArguments() ) {\n  if ( arg == null ) throw new KettleException(\"Null table name in truncate-tables entry\");\n}","typeGuard":"boolean canSaveToRepository(Repository rep, ObjectId id_job) {\n  return rep != null && rep.isConnected() && id_job != null;\n}","tryCatchPattern":"try {\n  jobEntry.saveRep(rep, metaStore, id_job);\n} catch ( KettleException e ) {\n  logError(\"Repository save failed for id_job=\" + id_job + \": \" + e.getCause(), e);\n  // export to .kjb as fallback so work is not lost\n  jobMeta.saveXMLFile(fallbackPath);\n  throw e;\n}","preventionTips":["Ensure the repository DB user has INSERT/UPDATE grants on R_JOBENTRY_ATTRIBUTE.","Avoid two users saving the same job simultaneously.","Monitor DB disk space and lock waits.","Export jobs to .kjb before risky repository maintenance."],"tags":["database","repository","kettle","persistence"],"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"}