pentaho/pentaho-kettle · error · KettleFileException

: Unable to read value metadata from input stream

Error message

 : Unable to read value metadata from input stream

What it means

ValueMetaBase.readMetaData reads this value meta's attributes back from a DataInputStream. If a low-level IOException occurs during the reads it is wrapped in a KettleFileException with this message; if the stream ends prematurely an EOFException is instead wrapped in KettleEOFException. The message means the metadata could not be read from the stream due to an I/O failure rather than a type problem.

Solutions

  1. Inspect getCause() for the root IOException (connection reset, disk I/O error, etc.) and fix that transport or file problem.
  2. Verify the stream was written by a compatible Kettle version; version mismatches can misalign reads and corrupt subsequent reads.
  3. Re-transfer or regenerate the corrupted stream/file and retry the read once the source is intact.
  4. Catch KettleEOFException separately upstream to distinguish a clean premature-end case from a hard I/O failure.

Example fix

// before
valueMeta.readMetaData(dataInputStream);
// after
try {
  valueMeta.readMetaData(dataInputStream);
} catch (KettleEOFException eof) {
  throw new KettleException("Stream ended before metadata was fully read", eof);
} catch (KettleFileException kfe) {
  throw new KettleException("I/O failure reading metadata: " + kfe.getCause(), kfe);
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (inputStream == null) throw new IllegalStateException("Input stream is null");
// check the socket/file is still alive before metadata reads
if (inputStream.available() < 0) throw new IllegalStateException("Stream already exhausted");

Try / catch

try {
  valueMeta.readMetaData(dataInputStream);
} catch (KettleEOFException eof) {
  throw new KettleException("Premature end of metadata stream", eof);
} catch (KettleFileException kfe) {
  throw new KettleException("I/O error reading metadata: " + kfe.getCause(), kfe);
}

Prevention

When it happens

Trigger: Calling readMetaData(DataInputStream) when the backing file/socket fails mid-read (disk error, connection reset, stream closed by another thread) but not at clean EOF. Any readString/readBoolean call inside the method throwing IOException triggers it.

Common situations: Network stream between clustered Carte servers reset mid-transfer; reading metadata from a truncated file; reading a stream produced by a different Kettle version whose field layout mismatches causing garbage/corrupt reads; storage media errors.

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/a09fedf557964c01. Report an issue: GitHub.

Appendix: source

Thrown at core/src/main/java/org/pentaho/di/core/row/value/ValueMetaBase.java:3231

      } else {
        dateFormatLocale = EnvUtil.createLocale( strDateFormatLocale );
      }

      // What is the time zone to use for date parsing?
      //
      String strTimeZone = readString( inputStream );
      if ( Utils.isEmpty( strTimeZone ) ) {
        dateFormatTimeZone = TimeZone.getDefault();
      } else {
        dateFormatTimeZone = EnvUtil.createTimeZone( strTimeZone );
      }

      // is string to number parsing lenient?
      lenientStringToNumber = inputStream.readBoolean();
    } catch ( EOFException e ) {
      throw new KettleEOFException( e );
    } catch ( IOException e ) {
      throw new KettleFileException( toString() + " : Unable to read value metadata from input stream", e );
    }

  }

  @Override
  public String getMetaXML() throws IOException {
    StringBuilder xml = new StringBuilder();

    xml.append( XMLHandler.openTag( XML_META_TAG ) );

    xml.append( XMLHandler.addTagValue( "type", getTypeDesc() ) );
    xml.append( XMLHandler.addTagValue( "storagetype", getStorageTypeCode( getStorageType() ) ) );

    switch ( storageType ) {
      case STORAGE_TYPE_INDEXED:
        xml.append( XMLHandler.openTag( "index" ) );

        // Save the indexed strings...

View on GitHub (pinned to f3058517a1)