pentaho/pentaho-kettle · error · KettleFileException

TextFileInput.Log.SingleLineFound

Error message

TextFileInput.Log.SingleLineFound

What it means

When parsing records that can span multiple lines (e.g. enclosed newlines), after consuming what looks like an end-of-line the parser re-checks for another line feed to distinguish single vs double line endings. If a single line feed is found where the configured format (DOS/Unix double endings context) requires a proper record terminator, a KettleFileException 'SingleLineFound' is thrown because the record structure does not match the configured format.

Solutions

  1. Set 'File format' to 'Mixed' in the step dialog if the file contains inconsistent line endings.
  2. Normalize the file's line endings (dos2unix / unix2dos) to match the configured format.
  3. Verify the enclosure and terminator settings; check the raw bytes around the failing line with a hex editor.
  4. Re-save the source file with a single consistent newline style.

Example fix

// before
fileFormat = "DOS"   // file has mixed LF/CRLF
// after
fileFormat = "Mixed"
Defensive patterns

Strategy: validation

Validate before calling

// detect mixed line endings before choosing the file format
byte[] bytes = java.nio.file.Files.readAllBytes(java.nio.file.Paths.get(filename));
boolean hasCrlf = new String(bytes).contains("\r\n");
boolean hasLoneLf = new String(bytes).replaceAll("\r\n", "").contains("\n");
if (hasCrlf && hasLoneLf) useFileFormat = "Mixed";

Try / catch

try { ... } catch (KettleFileException e) {
  logError("Line-ending structure mismatch; switch File format to Mixed or normalize the file", e);
  setErrors(1);
}

Prevention

When it happens

Trigger: File format is set to DOS or Unix (not Mixed) and the buffer logic in readOneRow encounters an end-of-line where, after moving the end-buffer pointer, data.newLineFound() is false — i.e. an odd/lonely line ending inconsistent with the configured multi-line record format.

Common situations: Mixing CRLF and LF line endings in one file while format is set to DOS; files edited on different OSes; wrong 'File format' selected in the step dialog for the actual file; stray lone CR/LF characters inside the data.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/trans/steps/csvinput/CsvInput.java:785

        // empty column at the end of the row (see the Jira case for details)
        if ( ( !newLineFound && outputIndex < data.fieldsMapping.size() ) || ( newLineFound && doubleLineEnd ) ) {

          int i = 0;
          while ( ( !data.newLineFound() && ( i < data.delimiter.length ) ) ) {
            data.moveEndBufferPointer();
            i++;
          }

          switch ( meta.getFileFormatTypeNr() ) {
            case TextFileInputMeta.FILE_FORMAT_DOS:
              if ( data.newLineFound() ) {
                if ( doubleLineEnd == true ) {
                  data.moveEndBufferPointerXTimes( data.encodingType.getLength() );
                } else {
                  //Re-check for a new Line
                  data.moveEndBufferPointerXTimes( data.encodingType.getLength() );
                  if ( !data.newLineFound() ) {
                    throw new KettleFileException( BaseMessages.getString( PKG, "TextFileInput.Log.SingleLineFound" ) );
                  }
                }
              }
              break;
            case TextFileInputMeta.FILE_FORMAT_MIXED:
              if ( data.isCarriageReturn() || doubleLineEnd ) {
                data.moveEndBufferPointerXTimes( data.encodingType.getLength() );
              }
              break;
          }
        }

        data.setStartBuffer( data.getEndBuffer() );
      }

      // See if we reached the end of the line.
      // If not, we need to skip the remaining items on the line until the next newline...
      //

View on GitHub (pinned to f3058517a1)