pentaho/pentaho-kettle · error · KettleException

JobFTPSPUT.UnableToLoadFromRepo

JobFTPSPUT.UnableToLoadFromRepo

Error message

JobFTPSPUT.UnableToLoadFromRepo

What it means

JobEntryFTPSPUT.loadRep() throws this KettleException when reading the job entry's attributes from the Kettle repository fails. Any KettleException from rep.getJobEntryAttributeString(...) or from FTPSConnection.getConnectionTypeByCode (invalid stored connection_type) is rethrown with the JobFTPSPUT.UnableToLoadFromRepo message plus the id_jobentry, with the database exception as cause.

Solutions

  1. Read the cause (KettleException/KettleDatabaseException) and verify repository connectivity and credentials.
  2. Check r_jobentry_attribute rows for the given id_jobentry and repair or delete the broken entry, then recreate it in Spoon.
  3. Confirm the stored connection_type matches a valid FTPSConnection code for the installed plugin version.
  4. Re-save the job entry with a matching plugin version so attributes are written in the expected format.

Example fix

// before: blindly loading with a stale ObjectId
JobEntryFTPSPUT entry = new JobEntryFTPSPUT();
entry.loadRep( rep, metaStore, unknownId, databases, slaveServers );
// after: verify the entry exists first
RowMetaAndData row = rep.getJobEntry( id_jobentry );
if ( row == null ) throw new KettleException( "Job entry " + id_jobentry + " missing from repository" );
entry.loadRep( rep, metaStore, id_jobentry, databases, slaveServers );
Defensive patterns

Strategy: try-catch

Validate before calling

// verify the entry exists and repository is reachable before loadRep
if ( !rep.isConnected() || rep.getJobEntry( id_jobentry ) == null ) {
  throw new KettleException( "Cannot load FTPSPUT entry " + id_jobentry + ": repository/entry unavailable" );
}

Try / catch

try {
  entry.loadRep( rep, metaStore, id_jobentry, databases, slaveServers );
} catch ( KettleException e ) {
  log.error( "Repo load failed for FTPSPUT entry " + id_jobentry + ": " + e.getCause() );
  throw new KettleException( "Check repository connectivity and r_jobentry_attribute rows, then reload", e );
}

Prevention

When it happens

Trigger: Loading an FTPSput job entry by ObjectId from a repository where the r_jobentry_attribute rows are missing/corrupt, the repository connection fails mid-read, or the stored connection_type string is not a recognized FTPS connection code.

Common situations: Repository schema drift after upgrading Pentaho; rows deleted from r_jobentry_attribute; repository database connectivity problems; entries saved by a newer plugin version with connection types the current code doesn't know.

Understand the failure class

Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.

Related errors


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

Appendix: source

Thrown at plugins/ftps/impl/src/main/java/org/pentaho/di/job/entries/ftpsput/JobEntryFTPSPUT.java:192

        Encr.decryptPasswordOptionallyEncrypted( rep.getJobEntryAttributeString( id_jobentry, "password" ) );
      remoteDirectory = rep.getJobEntryAttributeString( id_jobentry, "remoteDirectory" );
      localDirectory = rep.getJobEntryAttributeString( id_jobentry, "localDirectory" );
      wildcard = rep.getJobEntryAttributeString( id_jobentry, "wildcard" );
      binaryMode = rep.getJobEntryAttributeBoolean( id_jobentry, "binary" );
      timeout = rep.getJobEntryAttributeString( id_jobentry, "timeout" );
      remove = rep.getJobEntryAttributeBoolean( id_jobentry, "remove" );
      onlyPuttingNewFiles = rep.getJobEntryAttributeBoolean( id_jobentry, "only_new" );
      activeConnection = rep.getJobEntryAttributeBoolean( id_jobentry, "active" );

      proxyHost = rep.getJobEntryAttributeString( id_jobentry, "proxy_host" );
      proxyPort = rep.getJobEntryAttributeString( id_jobentry, "proxy_port" );
      proxyUsername = rep.getJobEntryAttributeString( id_jobentry, "proxy_username" );
      proxyPassword = rep.getJobEntryAttributeString( id_jobentry, "proxy_password" );
      connectionType =
        FTPSConnection.getConnectionTypeByCode( Const.NVL( rep.getJobEntryAttributeString(
          id_jobentry, "connection_type" ), "" ) );
    } catch ( KettleException dbe ) {
      throw new KettleException( BaseMessages.getString( PKG, "JobFTPSPUT.UnableToLoadFromRepo", String
        .valueOf( id_jobentry ) ), dbe );
    }
  }

  public void saveRep( Repository rep, IMetaStore metaStore, ObjectId id_job ) throws KettleException {
    try {
      rep.saveJobEntryAttribute( id_job, getObjectId(), "servername", serverName );
      rep.saveJobEntryAttribute( id_job, getObjectId(), "serverport", serverPort );
      rep.saveJobEntryAttribute( id_job, getObjectId(), "username", userName );
      rep.saveJobEntryAttribute( id_job, getObjectId(), "password", Encr
        .encryptPasswordIfNotUsingVariables( password ) );
      rep.saveJobEntryAttribute( id_job, getObjectId(), "remoteDirectory", remoteDirectory );
      rep.saveJobEntryAttribute( id_job, getObjectId(), "localDirectory", localDirectory );
      rep.saveJobEntryAttribute( id_job, getObjectId(), "wildcard", wildcard );
      rep.saveJobEntryAttribute( id_job, getObjectId(), "binary", binaryMode );
      rep.saveJobEntryAttribute( id_job, getObjectId(), "timeout", timeout );
      rep.saveJobEntryAttribute( id_job, getObjectId(), "remove", remove );
      rep.saveJobEntryAttribute( id_job, getObjectId(), "only_new", onlyPuttingNewFiles );

View on GitHub (pinned to f3058517a1)