pentaho/pentaho-kettle · error · KettleException

No control file specified

Error message

No control file specified

What it means

createCommandLine() demands a control file for the gpload/psql invocation. When meta.getControlFile() is null the step throws this KettleException, because psql cannot run the bulk load without the '-f <controlfile>' argument. It is a required-field validation error.

Solutions

  1. Set the control file path in the GP Bulk Loader step dialog (a valid gpload control file).
  2. If building metadata in code, call meta.setControlFile("/path/to/load.ctl") before execute().
  3. Re-save the step/transformation with a current plugin version so the controlFile attribute is written to XML.
  4. Pre-validate the meta in your orchestration code and fail with a descriptive message before the transformation runs.

Example fix

// before
GPBulkLoaderMeta meta = new GPBulkLoaderMeta();
meta.setPsqlpath("/usr/bin/psql");
// controlFile never set -> throws

// after
meta.setControlFile("/opt/gp/control/load.ctl");
Defensive patterns

Strategy: validation

Validate before calling

if (meta.getControlFile() == null || meta.getControlFile().trim().isEmpty()) {
  throw new IllegalArgumentException(
    "GP Bulk Loader: control file path is required before execute()");
}

Try / catch

try {
  execute(meta, wait);
} catch (KettleException e) {
  if (e.getMessage().contains("No control file specified")) {
    meta.setControlFile(generateControlFile());
    execute(meta, wait);
  } else throw e;
}

Prevention

When it happens

Trigger: execute() -> createCommandLine() runs while meta.getControlFile() is null: the control file field in the GP Bulk Loader step was left empty, or the metadata was loaded from XML missing that attribute.

Common situations: Step configured without generating/filling the control file path; transformation XML hand-edited or from an older schema lacking the controlFile element; programmatic GPBulkLoaderMeta usage without setControlFile(); user assumed the plugin would generate the control file automatically.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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

Appendix: source

Thrown at plugins/gp-bulk-loader/core/src/main/java/org/pentaho/di/trans/steps/gpbulkloader/GPBulkLoader.java:337

        throw new KettleException( "Error retrieving sqlldr string", ex );
      }
    } else {
      throw new KettleException( "No psql application specified" );
    }

    if ( meta.getControlFile() != null ) {
      try {
        FileObject fileObject =
          KettleVFS.getInstance( getTransMeta().getBowl() )
            .getFileObject( environmentSubstitute( meta.getControlFile() ), getTransMeta() );

        sb.append( " -n -f " );
        sb.append( enclosure ).append( KettleVFS.getFilename( fileObject ) ).append( enclosure );
      } catch ( Exception ex ) {
        throw new KettleException( "Error retrieving controlfile string", ex );
      }
    } else {
      throw new KettleException( "No control file specified" );
    }

    if ( meta.getLogFile() != null ) {
      try {
        FileObject fileObject =
          KettleVFS.getInstance( getTransMeta().getBowl() )
            .getFileObject( environmentSubstitute( meta.getLogFile() ), getTransMeta() );

        sb.append( " -o " );
        sb.append( enclosure ).append( KettleVFS.getFilename( fileObject ) ).append( enclosure );
      } catch ( Exception ex ) {
        throw new KettleException( "Error retrieving logfile string", ex );
      }
    }

    DatabaseMeta dm = meta.getDatabaseMeta();
    if ( dm != null ) {
      String user = Const.NVL( dm.getUsername(), "" );

View on GitHub (pinned to f3058517a1)