pentaho/pentaho-kettle · error · KettleException

Repository is already connected!

Error message

Repository is already connected!

What it means

KettleException thrown by KettleDatabaseRepositoryConnectionDelegate.connect when connect() is called while the repository already reports isConnected(). This is a state guard against double-connecting the same underlying Database object. It prevents resource leaks and re-initialization of an active connection.

Solutions

  1. Check repository.isConnected() before calling connect()
  2. Call repository.disconnect() before reconnecting
  3. Share the existing connection instead of reconnecting
  4. Synchronize connect/disconnect calls if multiple threads manage the lifecycle

Example fix

// before
repository.connect("admin", "admin"); // throws if already connected

// after
if (!repository.isConnected()) {
  repository.connect("admin", "admin");
}
Defensive patterns

Strategy: validation

Validate before calling

if (repository.isConnected()) { return; } // skip connect when already up
repository.connect(user, pass);

Type guard

boolean canConnect = !repository.isConnected();

Try / catch

try { if (!repository.isConnected()) repository.connect(u, p); } catch (KettleException e) { throw new RuntimeException("Repository connect failed", e); }

Prevention

When it happens

Trigger: Calling repository.connect() (or delegate.connect) twice without disconnect() in between, e.g., in plugin code that assumes a fresh connection each time while the repository singleton is already connected.

Common situations: Long-lived repository shared across threads where one component connects and another reconnects; retry logic that doesn't check isConnected() first.

Related errors


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

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/repository/kdr/delegates/KettleDatabaseRepositoryConnectionDelegate.java:139

    this.majorVersion = REQUIRED_MAJOR_VERSION;
    this.minorVersion = REQUIRED_MINOR_VERSION;
  }

  /**
   * Connect to the repository
   */
  public synchronized void connect() throws KettleException {
    connect( false, false );
  }

  public synchronized void connect( boolean no_lookup ) throws KettleException {
    connect( no_lookup, false );
  }

  public synchronized void connect( boolean no_lookup, boolean ignoreVersion ) throws KettleException {
    if ( repository.isConnected() ) {
      throw new KettleException( "Repository is already connected!" );
    }
    try {
      database.initializeVariablesFrom( null );
      database.connect();
      if ( !ignoreVersion ) {
        verifyVersion();
      }
      setAutoCommit( false );
      repository.setConnected( true );
      /*
       * Done lazily now.
       *
       * if (!no_lookup) { try { repository.connectionDelegate.setLookupStepAttribute();
       * repository.connectionDelegate.setLookupTransAttribute();
       * repository.connectionDelegate.setLookupJobEntryAttribute();
       * repository.connectionDelegate.setLookupJobAttribute(); } catch (KettleException dbe) { throw new
       * KettleException("Error setting lookup prep.statements", dbe); } }
       */

View on GitHub (pinned to f3058517a1)