{"record":{"id":"abd0fba6e495803f","repo":"pentaho/pentaho-kettle","slug":"error-while-preparing-the-copy","errorCode":null,"errorMessage":"Error while preparing the COPY ","messagePattern":"Error while preparing the COPY ","errorType":"exception","errorClass":"KettleException","httpStatus":null,"severity":"error","filePath":"plugins/postgresql-db-bulk-loader/impl/src/main/java/org/pentaho/di/trans/steps/pgbulkloader/PGBulkLoader.java","lineNumber":170,"sourceCode":"      statement.close();\n    }\n  }\n\n  private void do_copy( PGBulkLoaderMeta meta, boolean wait ) throws KettleException {\n    data.db = getDatabase( this, meta );\n    String copyCmd = getCopyCommand();\n    try {\n      connect();\n\n      checkClientEncoding();\n\n      processTruncate();\n\n      logBasic( \"Launching command: \" + copyCmd );\n      pgCopyOut = new PGCopyOutputStream( (PGConnection) data.db.getConnection(), copyCmd );\n\n    } catch ( Exception ex ) {\n      throw new KettleException( \"Error while preparing the COPY \" + copyCmd, ex );\n    }\n  }\n\n  @VisibleForTesting\n  Database getDatabase( LoggingObjectInterface parentObject, PGBulkLoaderMeta pgBulkLoaderMeta ) {\n    DatabaseMeta dbMeta = pgBulkLoaderMeta.getDatabaseMeta();\n    // If dbNameOverride is present, clone the origin db meta and override the DB name\n    String dbNameOverride = environmentSubstitute( pgBulkLoaderMeta.getDbNameOverride() );\n    if ( !Utils.isEmpty( dbNameOverride ) ) {\n      dbMeta = (DatabaseMeta) pgBulkLoaderMeta.getDatabaseMeta().clone();\n      dbMeta.setDBName( dbNameOverride.trim() );\n      logDebug( \"DB name overridden to the value: \" + dbNameOverride );\n    }\n    return new Database( parentObject, dbMeta );\n  }\n\n  void connect() throws KettleException {\n    if ( getTransMeta().isUsingUniqueConnections() ) {","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/plugins/postgresql-db-bulk-loader/impl/src/main/java/org/pentaho/di/trans/steps/pgbulkloader/PGBulkLoader.java#L152-L188","documentation":"do_copy wraps the setup of the PostgreSQL COPY operation — truncation and creation of the PGCopyOutputStream — in a try/catch and rethrows any failure as a KettleException prefixed with 'Error while preparing the COPY ' plus the command. It indicates the COPY could not even be started (connection or SQL problem), not that row data was bad.","triggerScenarios":"Any exception in the try block of do_copy: processTruncate() throwing (e.g. TRUNCATE fails), data.db.getConnection() failing or returning a non-PGConnection object (ClassCastException), or the PGCopyOutputStream constructor rejecting copyCmd (bad COPY SQL, missing table, insufficient privileges).","commonSituations":"Target table doesn't exist or was renamed; DB user lacks TRUNCATE privilege; connection dropped between init and first row; copyCmd malformed due to bad table/field names needing quoting; JDBC connection is not a PGConnection (wrong driver for the database).","solutions":["Read the wrapped cause (ex.getCause()) for the real failure; verify the target table exists and the connection user has INSERT/TRUNCATE rights","Run logBasic's printed 'Launching command: ...' COPY statement directly in psql to reproduce and fix the SQL","Confirm the database connection uses the PostgreSQL JDBC driver so getConnection() is a PGConnection","Fix the truncate step separately (see 'Error while truncating') if the cause comes from processTruncate"],"exampleFix":"// before\npgCopyOut = new PGCopyOutputStream( (PGConnection) data.db.getConnection(), copyCmd );\n// after (validate connection type first to get a clearer error)\nConnection conn = data.db.getConnection();\nif ( !( conn instanceof PGConnection ) ) {\n  throw new KettleException( \"Connection is not a PostgreSQL connection\" );\n}\npgCopyOut = new PGCopyOutputStream( (PGConnection) conn, copyCmd );","handlingStrategy":"try-catch","validationCode":"// before running the transformation\nif ( db.connectAndCheck( meta.getDatabaseMeta() ) == null ) {\n  throw new IllegalStateException( \"Cannot connect to PostgreSQL before bulk load\" );\n}\nDatabaseMeta dm = meta.getDatabaseMeta();\nif ( dm == null || !dm.getDatabaseTypeDesc().toLowerCase().contains( \"postgres\" ) ) {\n  throw new IllegalStateException( \"PGBulkLoader requires a PostgreSQL connection\" );\n}","typeGuard":"boolean isPgConnection( Connection c ) {\n  return c instanceof org.postgresql.PGConnection;\n}","tryCatchPattern":"try {\n  transformation.startExecution();\n} catch ( KettleException e ) {\n  Throwable cause = e.getCause();\n  log.error( \"COPY setup failed: \" + e.getMessage(), cause ); // cause holds the real SQL/Cast error\n}","preventionTips":["Test the database connection button in the step dialog before running","Ensure the target table exists and the user has INSERT and TRUNCATE privileges","Always use the PostgreSQL JDBC driver for this step","Execute the logged COPY command manually in psql to validate it"],"tags":["postgresql","copy","jdbc","database"],"backgroundTag":"sql-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"}