pentaho/pentaho-kettle · error · KettleException

Error retrieving controlfile string

Error message

Error retrieving controlfile string

What it means

After appending the psql executable, createCommandLine() resolves meta.getControlFile() through environmentSubstitute() and KettleVFS to append '-n -f <controlfile>' to the psql command. Any exception during that resolution is wrapped in this KettleException. The real cause (VFS error, bad path, unresolved variable) is attached as the cause.

Solutions

  1. Check ex.getCause() to see the actual VFS/resolution error and fix that root problem.
  2. Resolve all variables in the control file path (define them in kettle.properties or as transformation parameters).
  3. Verify the control file exists at the given path on the machine running Kettle (not just where psql will run).
  4. Use forward slashes / a supported VFS URI (file:///...) if the path contains Windows backslashes.

Example fix

// before
Control file: ${GP_CTL}/load.ctl   (GP_CTL undefined -> VFS/variable resolution throws)

// after: define the variable or hardcode a verified path
kettle.properties: GP_CTL=/opt/gp/control
Control file: ${GP_CTL}/load.ctl
Defensive patterns

Strategy: validation

Validate before calling

String ctl = meta.getControlFile();
if (ctl == null || ctl.trim().isEmpty())
  throw new IllegalArgumentException("Control file not set");
String resolved = transformation.environmentSubstitute(ctl);
if (resolved.contains("${"))
  throw new IllegalArgumentException("Unresolved variable in control file path: " + ctl);
if (!new java.io.File(resolved).canRead())
  throw new IllegalArgumentException("Control file not readable: " + resolved);

Try / catch

try {
  execute(meta, wait);
} catch (KettleException e) {
  if (e.getMessage().contains("Error retrieving controlfile string")) {
    logError("Control file resolution failed", e.getCause());
  } else throw e;
}

Prevention

When it happens

Trigger: createCommandLine() runs with meta.getControlFile() non-null, but KettleVFS.getFileObject(environmentSubstitute(controlFile)) throws: unknown VFS scheme, IO error resolving the file, or an unresolvable variable inside the control file path.

Common situations: Control file path references a variable not defined in kettle.properties or transformation parameters; control file lives on a remote VFS mount whose provider is missing; the control file was deleted/moved after the transformation was saved; Windows path with backslashes misinterpreted by VFS.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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

Appendix: source

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

        String psqlexec = KettleVFS.getFilename( fileObject );
        sb.append( enclosure ).append( psqlexec ).append( enclosure );
      } catch ( Exception ex ) {
        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 );
      }
    }

View on GitHub (pinned to f3058517a1)