apache/flink · error · ParseException

Line could not be parsed: '{}' ParserError {} Expect field

Error message

Line could not be parsed: '{}'
ParserError {} 
Expect field types: {} 
in file: {}

What it means

Thrown after a field parser returns a negative cursor (startPos < 0), indicating a parse failure with an error state such as NUMERIC_FORMAT_ERROR or EMPTY_FIELD. The message includes the offending line, the parser's ErrorState, the declared field types, and the source file path, so you can pinpoint which field/type/file combination failed. Like the other row checks, it only throws when lenient mode is off.

Source

Thrown at flink-core/src/main/java/org/apache/flink/api/common/io/GenericCsvInputFormat.java:412

            if (fieldIncluded[field]) {
                // parse field
                @SuppressWarnings("unchecked")
                FieldParser<Object> parser = (FieldParser<Object>) this.fieldParsers[output];
                Object reuse = holders[output];
                startPos =
                        parser.resetErrorStateAndParse(
                                bytes, startPos, limit, this.fieldDelim, reuse);
                holders[output] = parser.getLastResult();

                // check parse result
                if (startPos < 0) {
                    // no good
                    if (lenient) {
                        return false;
                    } else {
                        String lineAsString = new String(bytes, offset, numBytes, getCharset());
                        throw new ParseException(
                                "Line could not be parsed: '"
                                        + lineAsString
                                        + "'\n"
                                        + "ParserError "
                                        + parser.getErrorState()
                                        + " \n"
                                        + "Expect field types: "
                                        + fieldTypesToString()
                                        + " \n"
                                        + "in file: "
                                        + currentSplit.getPath());
                    }
                } else if (startPos == limit
                        && field != fieldIncluded.length - 1
                        && !FieldParser.endsWithDelimiter(bytes, startPos - 1, fieldDelim)) {
                    // We are at the end of the record, but not all fields have been read
                    // and the end is not a field delimiter indicating an empty last field.
                    if (lenient) {

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Inspect the ParserError token in the message to identify the failure class (e.g. NUMERIC_FORMAT_ERROR, EMPTY_FIELD) and fix the offending value or type.
  2. Pre-process the file to clean/normalize values (number separators, date formats, empty numeric cells).
  3. Enable lenient mode (format.setLenient(true)) to skip unparseable rows if dropping them is acceptable.
  4. Align the declared field types with the actual data; consider String + a parsing UDF for ambiguous columns.

Example fix

// before: throws on header row 'name,age'
format.setFieldTypesGeneric(Integer.class, String.class);
// after: skip header by reading first line as skip, or enable lenient
format.setSkipFirstLineAsHeader(true);
format.setLenient(true);
Defensive patterns

Strategy: validation

Validate before calling

// Pre-validate a sample against the declared types before submitting
Object[][] sample = readSample(path, 100);
Class<?>[] types = declaredFieldTypes;
for (Object[] row : sample) {
    for (int i = 0; i < row.length; i++) {
        if (row[i] != null && !types[i].isInstance(coerce(row[i], types[i]))) {
            throw new IllegalStateException("Column " + i + " value '" + row[i]
                + "' not coercible to " + types[i].getSimpleName());
        }
    }
}

Type guard

// Narrow ambiguous columns to String and validate in a map
DataStream<Row> safe = raw.map(r -> {
    String v = (String) r.getField(idx);
    try { return Integer.parseInt(v); }
    catch (NumberFormatException e) { return null; /* or side-output */ }
});

Try / catch

try {
    return format.nextRecord(reuse);
} catch (ParseException e) {
    log.warn("Skipping unparseable row in {}: {}", currentSplit, e.getMessage());
    return null; // or enable lenient up front
}

Prevention

When it happens

Trigger: A field value cannot be coerced to its declared type, e.g. 'abc' in an Integer column, an unparseable date string for java.sql.Date, a numeric overflow for the target primitive, or an empty value for a non-string type. ParserError in the message names the exact failure category.

Common situations: Header row left in the data file; locale-specific number formats ('1,5' vs '1.5'); date format mismatch between the file and Flink's expected SQL format; null/empty cells in a numeric column; schema drift after the producer added a column.

Related errors


AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14). Data as JSON: /api/errors/b24d639944a77c5f. Report an issue: GitHub.