{"record":{"id":"4ac093c5fc7541df","repo":"pentaho/pentaho-kettle","slug":"textfileinput-log-singlelinefound-4ac093","errorCode":"TextFileInput.Log.SingleLineFound","errorMessage":"TextFileInput.Log.SingleLineFound","messagePattern":"TextFileInput\\.Log\\.SingleLineFound","errorType":"exception","errorClass":"KettleFileException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/trans/steps/fileinput/text/TextFileInputUtils.java","lineNumber":366,"sourceCode":"\n\n  public static final String getLine( LogChannelInterface log, BufferedInputStreamReader reader, EncodingType encodingType,\n      int formatNr, StringBuilder line ) throws KettleFileException {\n    int c = 0;\n    line.setLength( 0 );\n    try {\n      switch( formatNr ) {\n        case TextFileInputMeta.FILE_FORMAT_DOS:\n          while ( c >= 0 ) {\n            c = reader.read();\n\n            if ( encodingType.isReturn( c ) || encodingType.isLinefeed( c ) ) {\n              c = reader.read(); // skip \\n and \\r\n              if ( !encodingType.isReturn( c ) && !encodingType.isLinefeed( c ) ) {\n                // make sure its really a linefeed or cariage return\n                // raise an error this is not a DOS file\n                // so we have pulled a character from the next line\n                throw new KettleFileException( BaseMessages.getString( PKG, \"TextFileInput.Log.SingleLineFound\" ) );\n              }\n              return line.toString();\n            }\n            if ( c >= 0 ) {\n              line.append( (char) c );\n            }\n          }\n          break;\n        case TextFileInputMeta.FILE_FORMAT_UNIX:\n          while ( c >= 0 ) {\n            c = reader.read();\n\n            if ( encodingType.isLinefeed( c ) || encodingType.isReturn( c ) ) {\n              return line.toString();\n            }\n            if ( c >= 0 ) {\n              line.append( (char) c );\n            }","sourceCodeStart":348,"sourceCodeEnd":384,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/trans/steps/fileinput/text/TextFileInputUtils.java#L348-L384","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Convert the file to Unix (\\n) or DOS (\\r\\n) line endings: dos2unix, or 'tr \\\\r \\\\n < in > out' for CR-only files.","Set the file's format/encoding type in the Content tab to match the actual line-ending style.","Preprocess the file in a prior step (e.g. a UDJC or shell script) to normalize line endings.","Check for stray \\r characters inside quoted fields and strip them.","Re-transfer the file in binary mode to avoid incomplete newline mangling."],"exampleFix":"// before: CR-only file fed directly to the step\n# file uses \\r endings, step expects \\r\\n\n// after: normalize line endings first\ntr '\\r' '\\n' < input.mac.txt > input.unix.txt","handlingStrategy":"fallback","validationCode":"// detect CR-only files before processing\ntry (BufferedInputStream in = new BufferedInputStream(Files.newInputStream(path))) {\n  int b, cr = 0, lf = 0, crlf = 0, prev = -1;\n  while ((b = in.read()) != -1) {\n    if (b == '\\r') { cr++; if (prev == '\\r') {} }\n    if (b == '\\n') { lf++; if (prev == '\\r') crlf++; }\n    prev = b;\n  }\n  if (cr > 0 && crlf == 0 && lf == 0) throw new KettleFileException(\"CR-only line endings detected; convert the file first\");\n}","typeGuard":"// a line is safe to parse only if it ends with \\n or \\r\\n, never a bare \\r mid-stream\nboolean isWellFormedLineEnding(String raw) { return !raw.contains(\"\\r\\n\\r\") && raw.chars().filter(c -> c=='\\r').count() <= raw.chars().filter(c -> c=='\\n').count(); }","tryCatchPattern":"try {\n  String line = TextFileInputUtils.getLine(log, reader, encodingType, ...\");\n} catch (KettleFileException e) {\n  if (String.valueOf(e.getMessage()).contains(\"SingleLineFound\")) {\n    // normalize line endings and restart the read\n  } else throw e;\n}","preventionTips":["Normalize files to \\n or \\r\\n with dos2unix before ingestion.","Transfer files in binary mode to avoid line-ending mangling.","Set the step's file format (DOS/Unix/Mixed) to match the source.","Reject or preprocess legacy CR-only files at intake."],"tags":["kettle","etl","line-endings","file-format"],"backgroundTag":"malformed-line-endings","analyzedSha":"f3058517a153da500bf4551f46d79b91bf8ec552","analyzedAt":"2026-09-13T14:04:16.340Z","contentChangedAt":"2026-09-13T14:04:16.340Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}