pentaho/pentaho-kettle · error · KettleException

GPload.Exception.DelimiterMissing

Error message

GPload.Exception.DelimiterMissing

What it means

GPLoad requires a field delimiter to write the data-file format into the gpload control file. If meta.getDelimiter() is empty (or empty after environment substitution and trim), the exception is thrown because gpload cannot parse the data file without a defined delimiter.

Solutions

  1. Enter a delimiter (e.g. tab, comma, '|') in the GPLoad step dialog.
  2. Define any delimiter environment variables in kettle.properties or the job's variable scope before execution.
  3. Avoid whitespace-only values; the trim check is designed to reject them.
  4. Set meta.setDelimiter("\t") programmatically before the step runs.

Example fix

// before
meta.setDelimiter("${DELIM}"); // variable undefined -> empty -> throws
// after
meta.setDelimiter("|"); // or define DELIM=| in kettle.properties
Defensive patterns

Strategy: validation

Validate before calling

String delim = meta.getDelimiter() == null ? null : meta.getDelimiter().trim();
if (delim == null || delim.isEmpty()) {
  throw new IllegalArgumentException("Delimiter must be set for GPLoad");
}

Try / catch

try {
  step.createControlFile(meta);
} catch (KettleException e) {
  if (e.getMessage().contains("DelimiterMissing")) { /* set delimiter or define variable */ }
  else throw e;
}

Prevention

When it happens

Trigger: getControlFileContents invoked while meta.getDelimiter() is null/empty, including the case where a delimiter given as an environment variable substitutes to an empty string.

Common situations: Delimiter field left blank in the dialog; ${DELIMITER} variable not defined; delimiter accidentally whitespace-only; metadata import dropped the setting.

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/e0424eec6e253d5b. Report an issue: GitHub.

Appendix: source

Thrown at plugins/gpload/core/src/main/java/org/pentaho/di/trans/steps/gpload/GPLoad.java:211

      }
    }

    // data file validation
    String dataFilename = meta.getDataFile();
    if ( !Utils.isEmpty( dataFilename ) ) {
      dataFilename = environmentSubstitute( dataFilename ).trim();
    }
    if ( Utils.isEmpty( dataFilename ) ) {
      throw new KettleException( BaseMessages.getString( PKG, "GPload.Exception.DataFileMissing" ) );
    }

    // delimiter validation
    String delimiter = meta.getDelimiter();
    if ( !Utils.isEmpty( delimiter ) ) {
      delimiter = environmentSubstitute( delimiter ).trim();
    }
    if ( Utils.isEmpty( delimiter ) ) {
      throw new KettleException( BaseMessages.getString( PKG, "GPload.Exception.DelimiterMissing" ) );
    }

    // Now we start building the contents
    StringBuffer contents = new StringBuffer( 1000 );

    // Source: GP Admin Guide 3.3.6, page 635:
    contents.append( GPLoad.GPLOAD_YAML_VERSION ).append( Const.CR );
    contents.append( "DATABASE: " );
    contents.append( environmentSubstitute( databaseMeta.getDatabaseName() ) );
    contents.append( Const.CR );
    contents.append( "USER: " ).append( environmentSubstitute( databaseMeta.getUsername() ) ).append( Const.CR );
    contents.append( "HOST: " ).append( environmentSubstitute( databaseMeta.getHostname() ) ).append( Const.CR );
    contents.append( "PORT: " ).append( environmentSubstitute( databaseMeta.getDatabasePortNumberString() ) ).append(
        Const.CR );
    contents.append( "GPLOAD:" ).append( Const.CR );
    contents.append( GPLoad.INDENT ).append( "INPUT: " ).append( Const.CR );
    contents.append( GPLoad.INDENT ).append( "- SOURCE: " ).append( Const.CR );

View on GitHub (pinned to f3058517a1)