pentaho/pentaho-kettle · error · KettleException
Unable to load Kettle database repository meta object
Error message
Unable to load Kettle database repository meta object
What it means
PurRepositoryMeta.loadXML() parses the XML node describing a Pentaho PUR repository connection and throws this KettleException when any exception occurs during parsing (malformed XML, missing nodes, or unexpected values). It wraps the original exception so repository metadata cannot be silently half-loaded. The failure means the repository meta object (connection definition) could not be reconstructed from XML.
Solutions
- Validate and repair the repository definition XML (repositories.xml or the node passed to loadXML); back it up and re-create the repository connection in Spoon.
- Check the wrapped cause exception (getCause()) to find the exact parse failure.
- Ensure the Kettle/Pentaho version writing the XML matches the version reading it; re-export the repository metadata from the correct version.
- Confirm the XML node name and structure match what the current PurRepositoryMeta.loadXML expects (repnode with sso_provider_name, sso_authorization_uri, etc.).
Example fix
// before
String xml = readRepositoriesXml(); // possibly corrupted/hand-edited
repoMeta.loadXML( XMLHandler.getSubNode( XMLHandler.loadXMLString( xml ), "repository" ) );
// after
String xml = readRepositoriesXmlFromBackupOrRecreate();
Node root = XMLHandler.loadXMLString( xml );
Node repnode = XMLHandler.getSubNode( root, "repository" );
if ( repnode == null ) {
throw new KettleException( "Repository node missing from repositories.xml - re-create the repository connection" );
}
repoMeta.loadXML( repnode ); Defensive patterns
Strategy: try-catch
Validate before calling
Node repnode = XMLHandler.getSubNode( root, "repository" ); if ( repnode == null ) throw new KettleException( "Repository XML node missing" );
Type guard
boolean isValidRepoNode( Node n ) { return n != null && XMLHandler.getTagValue( n, "description" ) != null; } Try / catch
try {
repoMeta.loadXML( repnode );
} catch ( KettleException e ) {
logError( "Repository meta load failed: " + e.getCause(), e );
repoMeta = recreateRepositoryMeta();
} Prevention
- Do not hand-edit repositories.xml; manage connections via Spoon
- Back up repositories.xml before Kettle upgrades
- Validate XML well-formedness before passing to loadXML
- Keep writer and reader Kettle versions aligned
When it happens
Trigger: Calling loadXML on an XML node that is not a valid PUR repository node: repnode is null, required child tags are absent/corrupt, or XMLHandler.getTagValue throws due to malformed XML structure.
Common situations: Hand-edited or corrupted ~/.kettle/repositories.xml, XML produced by a different Pentaho/Kettle version with a different node schema, truncated files, or repository definitions migrated between servers.
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
- GetXMLData.Error.UnableReadFile (localized message)
- Unable to load Kettle file repository meta object
- AnalyticQueryMeta.Exception.UnableToLoadStepInfoFromXML
- Could not retrieve version history of object with path
- DELETE_JOB : repository is read-only
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/9ed7e14b0b5d4d6b.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/pur/core/src/main/java/org/pentaho/di/repository/pur/PurRepositoryMeta.java:97
public void loadXML( Node repnode, List<DatabaseMeta> databases ) throws KettleException {
super.loadXML( repnode, databases );
try {
String url = XMLHandler.getTagValue( repnode, "repository_location_url" );
// remove trailing slash
String urlTrim = url.endsWith( "/" ) ? url.substring( 0, url.length() - 1 ) : url;
this.repositoryLocation = new PurRepositoryLocation( urlTrim );
this.versionCommentMandatory =
"Y".equalsIgnoreCase( XMLHandler.getTagValue( repnode, "version_comment_mandatory" ) );
this.authMethod = XMLHandler.getTagValue( repnode, "auth_method" );
// Normalize null or blank/whitespace auth method to default for backward compatibility
if ( this.authMethod == null || this.authMethod.trim().isEmpty() ) {
this.authMethod = AUTH_METHOD_USERNAME_PASSWORD;
}
setSsoProviderName( XMLHandler.getTagValue( repnode, "sso_provider_name" ) );
setSsoAuthorizationUri( XMLHandler.getTagValue( repnode, "sso_authorization_uri" ) );
setSsoRegistrationId( XMLHandler.getTagValue( repnode, "sso_registration_id" ) );
} catch ( Exception e ) {
throw new KettleException( "Unable to load Kettle database repository meta object", e );
}
}
public RepositoryCapabilities getRepositoryCapabilities() {
return new RepositoryCapabilities() {
public boolean supportsUsers() {
return true;
}
public boolean managesUsers() {
return true;
}
public boolean isReadOnly() {
return false;
}
public boolean supportsRevisions() {View on GitHub (pinned to f3058517a1)