pentaho/pentaho-kettle · error · KettleEOFException

End of file reached while reading value

Error message

End of file reached while reading value

What it means

This KettleEOFException is thrown by the Value.readObj method (invoked via the Value(InputStream) constructor and other deserialization paths) when an EOFException occurs partway through reading the value's type-specific data. It means the stream ended before all fields of the current value were consumed, i.e. truncated input.

Solutions

  1. Verify the stream/file is complete (compare byte count with what the writer reported) and re-transfer if truncated.
  2. Stop the read loop when the stream is exhausted instead of attempting further Value constructions.
  3. Use higher-level Kettle APIs (KettleFileTransaction / RowMeta.getRow) that signal clean end-of-data.
  4. Ensure the producer closes and flushes before the consumer reads to EOF.
  5. Catch KettleEOFException to detect end-of-data vs. KettleFileException for genuine corruption.

Example fix

// before
while ( true ) { Value v = new Value( in ); rows.add( v ); } // throws at EOF
// after
try {
  while ( true ) { rows.add( new Value( in ) ); }
} catch ( KettleEOFException e ) {
  // normal end of data
}
Defensive patterns

Strategy: try-catch

Validate before calling

// verify expected payload size before deserializing a record sequence
long expected = recordCount * avgRecordBytes; // or use stored length prefixes
if ( file.length() < expected ) throw new IOException( "File truncated: " + file.length() + " < " + expected );

Type guard

boolean hasData( InputStream in ) throws IOException {
  in.mark( 1 );
  int b = in.read();
  in.reset();
  return b != -1;
}

Try / catch

try {
  while ( hasData( in ) ) { rows.add( new Value( in ) ); }
} catch ( KettleEOFException e ) {
  log.warn( "Stream ended mid-value; expected " + recordCount + " rows, got " + rows.size() );
}

Prevention

When it happens

Trigger: Deserializing a sequence of Values when the stream is shorter than the expected value payload: truncated data file, closed socket mid-record, or a reader loop that keeps constructing Values after the stream is exhausted.

Common situations: Interrupted file transfer; producer crashed before flush/close; reading a Kettle binary file with a wrong expected record count; concurrent read/write on the same stream position.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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

Appendix: source

Thrown at core/src/main/java/org/pentaho/di/compatibility/Value.java:1775

            if ( dis.readBoolean() ) {
              setValue( new Date( dis.readLong() ) );
            }
            break;
          case VALUE_TYPE_NUMBER:
            setValue( dis.readDouble() );
            break;
          case VALUE_TYPE_INTEGER:
            setValue( dis.readLong() );
            break;
          case VALUE_TYPE_BOOLEAN:
            setValue( dis.readBoolean() );
            break;
          default:
            break;
        }
      }
    } catch ( EOFException e ) {
      throw new KettleEOFException( "End of file reached while reading value", e );
    } catch ( Exception e ) {
      throw new KettleEOFException( "Error reading value data from stream", e );
    }
  }

  /**
   * Compare 2 values of the same or different type! The comparison of Strings is case insensitive
   *
   * @param v
   *          the value to compare with.
   * @return -1 if The value was smaller, 1 bigger and 0 if both values are equal.
   */
  public int compare( Value v ) {
    return compare( v, true );
  }

  /**
   * Compare 2 values of the same or different type!

View on GitHub (pinned to f3058517a1)