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
- Inspect the cause (getCause()) to find the exact failing tag, then fix the XML attribute in the .kjb file.
- Re-open and re-save the job entry in Spoon so it regenerates valid XML for the installed plugin version.
- Verify the connection_type value matches a valid FTPSConnection code (e.g., as accepted by getConnectionTypeByCode).
- 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
- Avoid hand-editing .kjb XML; edit entries through Spoon.
- Keep plugin versions in sync between the instance that saves jobs and the one that loads them.
- Validate connection_type codes against FTPSConnection constants before writing XML.
- Keep job files under version control and validate after edits.
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
- ColumnExistsMeta.Exception.UnableToReadStepInfo
- CreditCardValidatorMeta.Exception.UnableToReadStepInfo
- CubeOutputMeta.Exception.UnableToLoadStepInfo
- DelayMeta.Exception.UnableToReadStepInfo
- DynamicSQLRowMeta.Exception.UnableToLoadStepInfo
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)