pentaho/pentaho-kettle · error · KettleFileException

TextFileInput.Log.SingleLineFound

TextFileInput.Log.SingleLineFound

Error message

TextFileInput.Log.SingleLineFound

What it means

TextFileInputUtils.getLine() throws KettleFileException 'TextFileInput.Log.SingleLineFound' when, after reading a carriage return (old Mac-style \r line ending), the next character is neither a return nor a linefeed. Since the reader treats \r as a complete line terminator, a character was consumed from the following line, meaning the file does not use DOS (\r\n) or Unix (\n) line endings as configured.

Solutions

  1. Convert the file to Unix (\n) or DOS (\r\n) line endings: dos2unix, or 'tr \\r \\n < in > out' for CR-only files.
  2. Set the file's format/encoding type in the Content tab to match the actual line-ending style.
  3. Preprocess the file in a prior step (e.g. a UDJC or shell script) to normalize line endings.
  4. Check for stray \r characters inside quoted fields and strip them.
  5. Re-transfer the file in binary mode to avoid incomplete newline mangling.

Example fix

// before: CR-only file fed directly to the step
# file uses \r endings, step expects \r\n
// after: normalize line endings first
tr '\r' '\n' < input.mac.txt > input.unix.txt
Defensive patterns

Strategy: fallback

Validate before calling

// detect CR-only files before processing
try (BufferedInputStream in = new BufferedInputStream(Files.newInputStream(path))) {
  int b, cr = 0, lf = 0, crlf = 0, prev = -1;
  while ((b = in.read()) != -1) {
    if (b == '\r') { cr++; if (prev == '\r') {} }
    if (b == '\n') { lf++; if (prev == '\r') crlf++; }
    prev = b;
  }
  if (cr > 0 && crlf == 0 && lf == 0) throw new KettleFileException("CR-only line endings detected; convert the file first");
}

Type guard

// a line is safe to parse only if it ends with \n or \r\n, never a bare \r mid-stream
boolean isWellFormedLineEnding(String raw) { return !raw.contains("\r\n\r") && raw.chars().filter(c -> c=='\r').count() <= raw.chars().filter(c -> c=='\n').count(); }

Try / catch

try {
  String line = TextFileInputUtils.getLine(log, reader, encodingType, ...");
} catch (KettleFileException e) {
  if (String.valueOf(e.getMessage()).contains("SingleLineFound")) {
    // normalize line endings and restart the read
  } else throw e;
}

Prevention

When it happens

Trigger: Reading a file via getLine()/sline() that contains bare \r characters (classic Mac line endings, or stray \r inside data) while the encoding type expects \r to end a line followed by \n; getLine() pulls the first char of the next line and raises the error.

Common situations: Files created on classic Mac OS or exported by legacy tools using CR-only endings; binary or mixed-format data accidentally fed to the text input step; files transferred between systems with partial line-ending conversion.

Related errors


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

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/trans/steps/fileinput/text/TextFileInputUtils.java:366


  public static final String getLine( LogChannelInterface log, BufferedInputStreamReader reader, EncodingType encodingType,
      int formatNr, StringBuilder line ) throws KettleFileException {
    int c = 0;
    line.setLength( 0 );
    try {
      switch( formatNr ) {
        case TextFileInputMeta.FILE_FORMAT_DOS:
          while ( c >= 0 ) {
            c = reader.read();

            if ( encodingType.isReturn( c ) || encodingType.isLinefeed( c ) ) {
              c = reader.read(); // skip \n and \r
              if ( !encodingType.isReturn( c ) && !encodingType.isLinefeed( c ) ) {
                // make sure its really a linefeed or cariage return
                // raise an error this is not a DOS file
                // so we have pulled a character from the next line
                throw new KettleFileException( BaseMessages.getString( PKG, "TextFileInput.Log.SingleLineFound" ) );
              }
              return line.toString();
            }
            if ( c >= 0 ) {
              line.append( (char) c );
            }
          }
          break;
        case TextFileInputMeta.FILE_FORMAT_UNIX:
          while ( c >= 0 ) {
            c = reader.read();

            if ( encodingType.isLinefeed( c ) || encodingType.isReturn( c ) ) {
              return line.toString();
            }
            if ( c >= 0 ) {
              line.append( (char) c );
            }

View on GitHub (pinned to f3058517a1)