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

  1. 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.
  2. Check the wrapped cause exception (getCause()) to find the exact parse failure.
  3. Ensure the Kettle/Pentaho version writing the XML matches the version reading it; re-export the repository metadata from the correct version.
  4. 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

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


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)