pentaho/pentaho-kettle · error · KettleXMLException
Unable to load job entry of type 'HTTP' from XML node
Error message
Unable to load job entry of type 'HTTP' from XML node
What it means
Thrown by JobEntryHTTP.loadXML when parsing the HTTP job entry's XML node (URL, arguments, headers, etc.) fails with a KettleXMLException. The cause is chained. It means the 'HTTP' job entry could not be loaded from a .kjb XML document.
Solutions
- Validate and fix the XML of the HTTP entry node; ensure <headers><header><name/><value/></header></headers> structure is intact.
- Check the chained KettleXMLException message for the precise parse failure.
- Re-export the job from Spoon to produce a well-formed file.
- If migrating versions, re-create the HTTP entry in the new Spoon version.
Example fix
// before: malformed header node
<headers><header><name>Auth</name></headers>
// after
<headers>
<header>
<name>Authorization</name>
<value>Bearer token</value>
</header>
</headers> Defensive patterns
Strategy: validation
Validate before calling
Document doc = XMLHandler.loadXMLFile(inputStream);
if (doc == null) throw new KettleException("Malformed .kjb file");
Node entry = XMLHandler.getSubNode(doc, "entry");
if (XMLHandler.getSubNode(entry, "headers") == null) {
logBasic("HTTP entry has no headers block; defaults will apply");
} Try / catch
try {
entry.loadXML(entryNode, databases, slaveServers, rep, metaStore);
} catch (KettleXMLException e) {
logError("HTTP entry XML load failed: " + e.getMessage());
// repair the node or re-export from Spoon
} Prevention
- Keep the <headers><header><name/><value/></header></headers> structure intact.
- Validate .kjb XML after any scripted manipulation.
- Avoid editing job files outside Spoon.
- Match Pentaho versions between file creation and loading.
When it happens
Trigger: Calling loadXML on JobEntryHTTP when XMLHandler navigation (getSubNode, getSubNodeByNr on <headers>/<header> nodes) throws KettleXMLException — malformed XML or missing/invalid node structure inside the entry block.
Common situations: Hand-edited or truncated .kjb files; header nodes removed or renamed manually; version drift between the file's schema and the current Pentaho version; bad encoding after editing on another platform.
Understand the failure class
Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.
Related errors
- ERROR_0001
- JobDosToUnix.Error.Exception.UnableLoadXML
- JobEntryDeleteFolders.UnableToLoadFromXml
- JobEntryDeleteResultFilenames.CanNotLoadFromXML
- JobEntrySimple.Error.Exception.UnableLoadXML
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/b3431bbe3cfe8278.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/job/entries/http/JobEntryHTTP.java:272
password = Encr.decryptPasswordOptionallyEncrypted( XMLHandler.getTagValue( entrynode, TAG_PASSWORD ) );
proxyHostname = XMLHandler.getTagValue( entrynode, TAG_PROXY_HOST );
proxyPort = XMLHandler.getTagValue( entrynode, TAG_PROXY_PORT );
nonProxyHosts = XMLHandler.getTagValue( entrynode, TAG_NON_PROXY_HOSTS );
addfilenameresult =
"Y".equalsIgnoreCase( Const.NVL( XMLHandler.getTagValue( entrynode, TAG_ADD_FILENAME_RESULT ), "Y" ) );
Node headers = XMLHandler.getSubNode( entrynode, TAG_HEADERS );
// How many field headerName?
int nrHeaders = XMLHandler.countNodes( headers, TAG_HEADER );
allocate( nrHeaders );
for ( int i = 0; i < nrHeaders; i++ ) {
Node fnode = XMLHandler.getSubNodeByNr( headers, TAG_HEADER, i );
headerName[ i ] = XMLHandler.getTagValue( fnode, TAG_HEADER_NAME );
headerValue[ i ] = XMLHandler.getTagValue( fnode, TAG_HEADER_VALUE );
}
} catch ( KettleXMLException xe ) {
throw new KettleXMLException( "Unable to load job entry of type 'HTTP' from XML node", xe );
}
}
@Override
public void loadRep( Repository rep, IMetaStore metaStore, ObjectId idJobEntry, List<DatabaseMeta> databases,
List<SlaveServer> slaveServers ) throws KettleException {
try {
url = rep.getJobEntryAttributeString( idJobEntry, TAG_URL );
targetFilename = rep.getJobEntryAttributeString( idJobEntry, TAG_TARGET_FILENAME );
fileAppended = rep.getJobEntryAttributeBoolean( idJobEntry, TAG_FILE_APPENDED );
dateTimeAdded = rep.getJobEntryAttributeBoolean( idJobEntry, TAG_DATE_TIME_ADDED );
targetFilenameExtension = Const.NVL( rep.getJobEntryAttributeString( idJobEntry, TAG_TARGET_FILENAME_EXTENSION ),
rep.getJobEntryAttributeString( idJobEntry, TAG_TARGET_FILENAME_EXTENTION ) );
uploadFilename = rep.getJobEntryAttributeString( idJobEntry, TAG_UPLOAD_FILENAME );
urlFieldname = rep.getJobEntryAttributeString( idJobEntry, TAG_URL_FIELDNAME );
uploadFieldname = rep.getJobEntryAttributeString( idJobEntry, TAG_UPLOAD_FIELDNAME );View on GitHub (pinned to f3058517a1)