pentaho/pentaho-kettle · error · KettleFileException

Output filename not set!

Error message

Output filename not set!

What it means

When the filename comes from a field, the field's string value for the current row is used as the output file name. If that value is null the step has no file to open, so it throws KettleFileException (message 'Output filename not set!').

Solutions

  1. Fix upstream data so the filename field is never null (e.g. coalesce/default value via 'Value Mapper' or 'If field value is null')
  2. Disable 'File name in field?' and specify a static filename with variables if the name is constant
  3. Filter out rows with null filename before the step

Example fix

// before: rows may carry null filename
// after: add 'If field value is null' step setting null -> '/tmp/default.csv', or:
filename = Utils.isEmpty( data.fileName ) ? "/tmp/default.csv" : buildFilename( environmentSubstitute( data.fileName ), true );
Defensive patterns

Strategy: validation

Validate before calling

Object v = row[ rowIndex ];
if ( v == null ) throw new KettleException( "Filename field is null for this row" );

Type guard

boolean hasFileName( RowMetaInterface m, Object[] row, int idx ) { return idx >= 0 && row[idx] != null && m.getValueMeta( idx ).getString( row[idx] ) != null; }

Try / catch

try { filename = getOutputFileName( row ); } catch ( KettleFileException e ) { logError( "Row has null filename: " + row ); rejectRow( row ); }

Prevention

When it happens

Trigger: FileName field enabled and the field's value is null for the row being written (data.fileName == null in getOutputFileName).

Common situations: Input rows with missing/empty filename column; a lookup failed to fill the field; null handling not configured upstream.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/trans/steps/textfileoutput/TextFileOutput.java:262

      if ( data.writer != null ) {
        filename = data.getFileStreamsCollection().getLastFileName( );
      } else {
        filename = meta.getFileName();
        if ( filename == null ) {
          throw new KettleFileException( BaseMessages.getString( PKG, "TextFileOutput.Exception.FileNameNotSet" ) );
        }
        filename = buildFilename( environmentSubstitute( filename ), true );
      }
    } else {
      data.fileNameFieldIndex = getInputRowMeta().indexOfValue( meta.getFileNameField() );
      if ( data.fileNameFieldIndex < 0 ) {
        throw new KettleStepException( BaseMessages.getString( PKG, "TextFileOutput.Exception.FileNameFieldNotFound", meta.getFileNameField() ) );
      }
      data.fileNameMeta = getInputRowMeta().getValueMeta( data.fileNameFieldIndex );
      data.fileName = data.fileNameMeta.getString( row[data.fileNameFieldIndex] );

      if ( data.fileName == null ) {
        throw new KettleFileException( BaseMessages.getString( PKG, "TextFileOutput.Exception.FileNameNotSet" ) );
      }

      filename = buildFilename( environmentSubstitute( data.fileName ), true );
    }
    return filename;
  }

  public int getFlushInterval(  )  {
    String flushIntervalStr = getTransMeta().getVariable( "KETTLE_FILE_OUTPUT_MAX_STREAM_LIFE" );
    int flushInterval = 0;
    if ( flushIntervalStr != null ) {
      try {
        flushInterval = Integer.parseInt( flushIntervalStr );
      } catch ( Exception ex ) {
        // Do nothing
      }
    }
    return flushInterval;

View on GitHub (pinned to f3058517a1)