pentaho/pentaho-kettle · error · KettleStepException

Error writing line

Error message

Error writing line

What it means

TextFileOutput.writeRow serializes the formatted fields and writes the line plus binary newline to the writer. Any exception in that block (IO error, formatting failure, encoding problem) is wrapped in KettleStepException 'Error writing line'.

Solutions

  1. Inspect the wrapped cause (getCause()) to find the real failure (IO vs value formatting)
  2. Check disk space and output stream state
  3. Validate field values/formats in the step's Fields tab (format, length, precision)
Defensive patterns

Strategy: try-catch

Validate before calling

// validate field formats before the run
for ( TextFileField f : fields ) { if ( f.getFormat() != null ) checkFormatSupported( f.getFormat() ); }

Try / catch

try { writeRow( row ); } catch ( KettleStepException e ) { Throwable cause = e.getCause(); logError( "Write failed: " + cause ); if ( cause instanceof IOException ) checkDiskAndStream(); }

Prevention

When it happens

Trigger: data.writer.write() of the field bytes or binaryNewline throws: stream closed, disk full, or formatField throws KettleValueException for a field value.

Common situations: Disk full mid-transformation; file closed by 'split every N rows' logic race; incompatible field values producing formatting errors.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


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

Appendix: source

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

         * Only write the fields specified!
         */
        for ( int i = 0; i < meta.getOutputFields().length; i++ ) {
          if ( i > 0 && data.binarySeparator.length > 0 ) {
            data.writer.write( data.binarySeparator );
          }

          ValueMetaInterface v = meta.getMetaWithFieldOptions()[ i ];
          Object valueData = r[ data.fieldnrs[ i ] ];
          writeField( v, valueData, data.binaryNullValue[ i ] );
        }
      }

      data.writer.write( data.binaryNewline );

      incrementLinesOutput();

    } catch ( Exception e ) {
      throw new KettleStepException( "Error writing line", e );
    }
  }

  private byte[] formatField( ValueMetaInterface v, Object valueData ) throws KettleValueException {
    if ( v.isString() ) {
      if ( v.isStorageBinaryString() && v.getTrimType() == ValueMetaInterface.TRIM_TYPE_NONE && v.getLength() < 0
          && Utils.isEmpty( v.getStringEncoding() ) ) {
        return (byte[]) valueData;
      } else {
        String svalue = ( valueData instanceof String ) ? (String) valueData : v.getString( valueData );
        return convertStringToBinaryString( v, Const.trimToType( svalue, v.getTrimType() ) );
      }
    } else {
      return v.getBinaryString( valueData );
    }
  }

  private byte[] convertStringToBinaryString( ValueMetaInterface v, String string ) throws KettleValueException {

View on GitHub (pinned to f3058517a1)