{"record":{"id":"df06aea2620ff81c","repo":"pentaho/pentaho-kettle","slug":"database-exception-errorclosingcallablestatement","errorCode":null,"errorMessage":"Database.Exception.ErrorClosingCallableStatement","messagePattern":"Database\\.Exception\\.ErrorClosingCallableStatement","errorType":"exception","errorClass":"KettleDatabaseException","httpStatus":null,"severity":"warning","filePath":"core/src/main/java/org/pentaho/di/core/database/Database.java","lineNumber":4952,"sourceCode":"        }\n      } while ( moreResults || ( updateCount > -1 ) );\n\n      return ret;\n    } catch ( Exception ex ) {\n      throw new KettleDatabaseException( \"Unable to call procedure\", ex );\n    }\n  }\n\n  public void closeProcedureStatement() throws KettleDatabaseException {\n    // CHE: close the callable statement involved in the stored\n    // procedure call!\n    try {\n      if ( cstmt != null ) {\n        cstmt.close();\n        cstmt = null;\n      }\n    } catch ( SQLException ex ) {\n      throw new KettleDatabaseException( BaseMessages.getString(\n        PKG, \"Database.Exception.ErrorClosingCallableStatement\" ), ex );\n    }\n  }\n\n  /**\n   * Return SQL CREATION statement for a Table\n   *\n   * @param tableName The table to create\n   * @throws KettleDatabaseException\n   */\n\n  public String getDDLCreationTable( String tableName, RowMetaInterface fields ) throws KettleDatabaseException {\n\n    // First, check for reserved SQL in the input row r...\n    databaseMeta.quoteReservedWords( fields );\n    String quotedTk = databaseMeta.quoteField( null );\n\n    return getCreateTableStatement( tableName, fields, quotedTk, false, null, true );","sourceCodeStart":4934,"sourceCodeEnd":4970,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/core/src/main/java/org/pentaho/di/core/database/Database.java#L4934-L4970","documentation":"Thrown by Database.closeCallableStatement() (Database.java:4952) when ResultSet.freeing the CallableStatement via close() fails with a SQLException during cleanup of a stored-procedure call. It wraps the underlying SQLException with the message 'Error closing Callable Statement'. Usually a symptom of an already-broken connection rather than the primary problem.","triggerScenarios":"Calling Database.closeCallableStatement() (or Database.closeProcedureStatement()) after executing a stored procedure call, when the JDBC CallableStatement.close() throws SQLException — e.g. the connection was already closed, dropped by the DB, or the statement is in an inconsistent state after a failed execution.","commonSituations":"Long-running transformations where the DB or firewall drops idle connections between proc calls; calling closeCallableStatement on an already-closed Database; stored procedure execution errors leaving the statement in a bad state; connection-pool evictions in clustered environments.","solutions":["Inspect the wrapped SQLException (getCause()) for the true reason — fix the underlying connection problem first","Ensure the Database object itself is open and connected before calling closeCallableStatement","Use connection pooling/validation queries (setConnectionValidationQuery / validation interval) so dead connections are recycled","Wrap cleanup in try-catch and log rather than letting the cleanup failure mask the real proc-call exception","Upgrade JDBC driver if the driver throws spuriously on close of completed statements"],"exampleFix":"// before\ncstmt.close();\n// after\ntry {\n  if ( cstmt != null ) {\n    cstmt.close();\n  }\n} catch ( SQLException cleanupEx ) {\n  log.logMinimal( \"Ignored error closing callable statement\", cleanupEx ); // don't mask primary exception\n}","handlingStrategy":"try-catch","validationCode":"if ( database != null && database.getConnection() != null && !database.getConnection().isClosed() ) {\n  database.closeCallableStatement();\n}","typeGuard":"boolean isConnectionAlive( Database db ) {\n  try { return db != null && db.getConnection() != null && !db.getConnection().isClosed(); }\n  catch ( SQLException e ) { return false; }\n}","tryCatchPattern":"try {\n  database.closeCallableStatement();\n} catch ( KettleDatabaseException e ) {\n  SQLException cause = (SQLException) e.getCause();\n  log.warn( \"Callable statement cleanup failed: \" + cause.getMessage(), cause );\n}","preventionTips":["Always check the Database/connection is open before cleanup calls","Enable connection validation queries with a short validation interval","Log and swallow cleanup exceptions so they don't mask the primary error","Keep proc-call executions short to avoid idle-connection drops"],"tags":["jdbc","database","cleanup","callable-statement"],"backgroundTag":"database-query-failed","analyzedSha":"f3058517a153da500bf4551f46d79b91bf8ec552","analyzedAt":"2026-09-13T14:04:16.340Z","contentChangedAt":"2026-09-13T14:04:16.340Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}