pentaho/pentaho-kettle · error · KettleXMLException

JobFTPSPUT.Log.UnableToLoadFromXml

JobFTPSPUT.Log.UnableToLoadFromXml

Error message

JobFTPSPUT.Log.UnableToLoadFromXml

What it means

JobEntryFTPSPUT.loadXML() wraps any KettleXMLException raised while parsing the job entry's XML node in a new KettleXMLException with the JobFTPSPUT.Log.UnableToLoadFromXml message. It indicates the <entry type='FTPSPUT'> element could not be deserialized — a required tag was missing/malformed or the connection_type code was invalid — and the original parse exception is attached as the cause.

Solutions

  1. Inspect the cause (getCause()) to find the exact failing tag, then fix the XML attribute in the .kjb file.
  2. Re-open and re-save the job entry in Spoon so it regenerates valid XML for the installed plugin version.
  3. Verify the connection_type value matches a valid FTPSConnection code (e.g., as accepted by getConnectionTypeByCode).
  4. Ensure the FTPS plugin of the matching version is installed on the target Pentaho instance.

Example fix

<!-- before -->
<connection_type>FTPS_IMPLICIT_WRONG</connection_type>
<!-- after: use a valid code -->
<connection_type>FTPS_AUTH_SSL</connection_type>
Defensive patterns

Strategy: try-catch

Validate before calling

// validate the FTPSPUT entry XML before loadXML
String connType = XMLHandler.getTagValue( entrynode, "connection_type" );
if ( connType != null && FTPSConnection.getConnectionTypeByCodeSafe( connType ) == null ) {
  throw new IllegalArgumentException( "Unknown FTPS connection_type: " + connType );
}

Try / catch

try {
  entry.loadXML( entrynode, databases, metaStore );
} catch ( KettleXMLException e ) {
  log.error( "Failed to load FTPSPUT entry XML: " + e.getMessage() + "; cause=" + e.getCause() );
  throw new KettleException( "Fix the FTPSput entry XML in the .kjb file and reload", e );
}

Prevention

When it happens

Trigger: Loading a .kjb job file whose FTPSput entry XML is hand-edited or produced by an older/newer plugin version, so XMLHandler.getTagValue returns unexpected values or FTPSConnection.getConnectionTypeByCode receives an unknown connection_type code and throws.

Common situations: Manually editing or generating job XML; migrating jobs between Kettle versions where the FTPS plugin schema changed; corrupted/truncated .kjb files; a connection_type attribute that doesn't match any FTPSConnection type code.

Related errors


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

Appendix: source

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

      password = Encr.decryptPasswordOptionallyEncrypted( XMLHandler.getTagValue( entrynode, "password" ) );
      remoteDirectory = XMLHandler.getTagValue( entrynode, "remoteDirectory" );
      localDirectory = XMLHandler.getTagValue( entrynode, "localDirectory" );
      wildcard = XMLHandler.getTagValue( entrynode, "wildcard" );
      binaryMode = "Y".equalsIgnoreCase( XMLHandler.getTagValue( entrynode, "binary" ) );
      timeout = XMLHandler.getTagValue( entrynode, "timeout" );
      remove = "Y".equalsIgnoreCase( XMLHandler.getTagValue( entrynode, "remove" ) );
      onlyPuttingNewFiles = "Y".equalsIgnoreCase( XMLHandler.getTagValue( entrynode, "only_new" ) );
      activeConnection = "Y".equalsIgnoreCase( XMLHandler.getTagValue( entrynode, "active" ) );

      proxyHost = XMLHandler.getTagValue( entrynode, "proxy_host" );
      proxyPort = XMLHandler.getTagValue( entrynode, "proxy_port" );
      proxyUsername = XMLHandler.getTagValue( entrynode, "proxy_username" );
      proxyPassword = XMLHandler.getTagValue( entrynode, "proxy_password" );
      connectionType =
        FTPSConnection.getConnectionTypeByCode( Const.NVL(
          XMLHandler.getTagValue( entrynode, "connection_type" ), "" ) );
    } catch ( KettleXMLException xe ) {
      throw new KettleXMLException( BaseMessages.getString( PKG, "JobFTPSPUT.Log.UnableToLoadFromXml" ), xe );
    }
  }

  public void loadRep( Repository rep, IMetaStore metaStore, ObjectId id_jobentry, List<DatabaseMeta> databases,
    List<SlaveServer> slaveServers ) throws KettleException {
    try {
      serverName = rep.getJobEntryAttributeString( id_jobentry, "servername" );
      serverPort = rep.getJobEntryAttributeString( id_jobentry, "serverport" );
      userName = rep.getJobEntryAttributeString( id_jobentry, "username" );
      password =
        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" );

View on GitHub (pinned to f3058517a1)