pentaho/pentaho-kettle · error · KettleEOFException
End of file reached
Error message
End of file reached
What it means
This KettleEOFException is thrown by the Value(InputStream) constructor when readObj() hits an EOFException while deserializing a Value from a DataInputStream. It means the underlying stream ended before the complete serialized value could be read, i.e. truncated or exhausted data. The library throws it to distinguish 'stream ended prematurely' from other deserialization failures, which surface as KettleFileException instead.
Solutions
- Verify the source file/stream is complete and uncorrupted (check file size vs. expected size, re-download or re-export).
- Ensure the writer finished and flushed/closed the stream before the reader starts (or retry after the producer completes).
- Wrap the reading loop in a check for stream availability before constructing Value, or use the Kettle row-input APIs (e.g. RowMeta.getRow) which handle EOF signaling gracefully.
- Upgrade/align PDI versions on writer and reader — serialization format mismatches can cause premature EOF.
- Catch KettleEOFException explicitly and treat it as a normal end-of-input signal if reading a sequence of values.
Example fix
// before
Value v = new Value( inputStream ); // throws KettleEOFException on truncated stream
// after
try {
Value v = new Value( inputStream );
} catch ( KettleEOFException e ) {
// end of stream: treat as end-of-input or flag truncation
logger.warn( "Truncated value stream at byte offset " + bytesRead, e );
return;
} Defensive patterns
Strategy: try-catch
Validate before calling
// before reading
if ( !inputStreamAvailable( in ) ) {
throw new IllegalStateException( "Stream already exhausted; cannot read Value" );
}
private boolean inputStreamAvailable( InputStream in ) throws IOException {
if ( in instanceof BufferedInputStream ) return true; // cannot peek generic streams safely
return in.available() > 0 || in.read() != -1;
} Type guard
// ensure the stream is a known-size, complete source
boolean isCompleteSource( File f, long expectedBytes ) {
return f.isFile() && f.length() == expectedBytes;
} Try / catch
try {
Value v = new Value( in );
} catch ( KettleEOFException e ) {
// end-of-input or truncation: stop reading, verify completeness
handleEndOfStream( e );
} Prevention
- Always verify producer completion (file finalization, checksum) before reading serialized data.
- Use Kettle's row-level input APIs that signal EOF instead of raw Value construction.
- Keep writer and reader PDI versions aligned.
- Retry truncated transfers automatically and compare byte counts.
- Treat KettleEOFException as end-of-data, not as a retryable fault.
When it happens
Trigger: Constructing new Value( InputStream ) (or code paths that deserialize Value rows from files/sockets) when the stream has fewer bytes than the serialized value requires: truncated kettle .ktr/.kjb data files, a socket/pipe closed mid-record, or reading past the last record of a file.
Common situations: Reading a partially-downloaded or partially-written Kettle serialized file; a producer process crashed mid-write; using an InputStream that was already fully consumed by a previous reader; HDFS/FTP transfer size mismatches; incorrect row-count assumptions when streaming value sequences.
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
- End of file reached while reading value
- End of file while reading the number of metadata values in…
- Error reading value data from stream
- KettleEOFException wrapping EOFException (no message)
- End of file reached
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/2d8d07052e7102fe.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/pentaho/di/compatibility/Value.java:1639
default:
break;
}
}
}
/**
* Read the Value, including meta-data from a DataInputStream
*
* @param is
* The InputStream to read the value from
* @throws KettleFileException
* when the Value couldn't be created by reading it from the DataInputStream.
*/
public Value( InputStream is ) throws KettleFileException {
try {
readObj( new DataInputStream( is ) );
} catch ( EOFException e ) {
throw new KettleEOFException( "End of file reached", e );
} catch ( Exception e ) {
throw new KettleFileException( "Error reading from data input stream", e );
}
}
/**
* Write the data of this Value, without the meta-data to a DataOutputStream
*
* @param dos
* The DataOutputStream to write the data to
* @return true if all went well, false if something went wrong.
*/
public boolean writeData( DataOutputStream dos ) throws KettleFileException {
try {
// Is the value NULL?
dos.writeBoolean( isNull() );
// Handle Content -- only when not NULLView on GitHub (pinned to f3058517a1)