pentaho/pentaho-kettle · error · KettleFileException

: Unable to write value metadata to output stream

Error message

 : Unable to write value metadata to output stream

What it means

ValueMetaBase.writeMetaData serializes this value metadata object's attributes to a DataOutputStream. If any underlying stream write throws an IOException, it is wrapped in a KettleFileException with this message, prefixed by the value meta's name. It means the metadata could not be persisted to the stream, almost always due to an I/O problem or a closed stream, not a bad data type.

Solutions

  1. Check the cause (KettleFileException.getCause()) for the real IOException; fix the underlying stream (closed connection, full disk, broken socket).
  2. Ensure the DataOutputStream is open and flushed before calling writeMetaData and that both writer and reader sides use compatible stream lifecycles.
  3. Verify enough disk space and write permissions for the target file when serializing to disk.
  4. Keep Pentaho/Kettle versions in sync on both ends of the stream so the metadata serialization format matches.

Example fix

// before: writing to a stream that may already be closed
rowMeta.writeMetaData(outputStream);
// after: guard the stream state and close in finally
if (outputStream != null) {
  try {
    rowMeta.writeMetaData(outputStream);
    outputStream.flush();
  } catch (KettleFileException e) {
    throw new KettleException("Failed to write row metadata", e);
  }
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (outputStream == null || outputStream.checkError()) throw new IllegalStateException("Stream not writable");
File target = new File(path);
if (target.getUsableSpace() < 1024 * 1024) throw new IllegalStateException("Low disk space");

Try / catch

try {
  valueMeta.writeMetaData(dataOutputStream);
  dataOutputStream.flush();
} catch (KettleFileException e) {
  Throwable root = e.getCause();
  logError("Metadata write failed: " + (root != null ? root.getMessage() : e.getMessage()), e);
  throw new KettleException("Metadata write failed", e);
}

Prevention

When it happens

Trigger: Calling writeMetaData(DataOutputStream) when the underlying stream is closed, the socket/file backing it has failed mid-write, or disk is full. Any IOException inside the long block of writeString/writeBoolean calls (e.g. writing name, comments, format masks, timezone ID) triggers it.

Common situations: Transrowing metadata between transformations over a network stream that dropped; writing row metadata to a file on a full filesystem; serializing metadata inside a stopped/aborted step whose stream was already closed; a partially-written .ktr/.kwb artifact cache.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


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

Appendix: source

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

      // Sorting information
      outputStream.writeBoolean( sortedDescending );

      // Padding information
      outputStream.writeBoolean( outputPaddingEnabled );

      // date format lenient?
      outputStream.writeBoolean( dateFormatLenient );

      // date format locale?
      writeString( outputStream, dateFormatLocale != null ? dateFormatLocale.toString() : null );

      // date time zone?
      writeString( outputStream, dateFormatTimeZone != null ? dateFormatTimeZone.getID() : null );

      // string to number conversion lenient?
      outputStream.writeBoolean( lenientStringToNumber );
    } catch ( IOException e ) {
      throw new KettleFileException( toString() + " : Unable to write value metadata to output stream", e );
    }
  }

  /**
   * Load the attributes of this particular value meta object from the input stream. Loading the type is not handled
   * here, this should be read from the stream previously!
   *
   * @param inputStream
   *          the input stream to read from
   * @throws KettleFileException
   *           In case there was a IO problem
   * @throws KettleEOFException
   *           If we reached the end of the stream
   */
  @Override
  public void readMetaData( DataInputStream inputStream ) throws KettleFileException, KettleEOFException {

    // Loading the type is not handled here, this should be read from the stream previously!

View on GitHub (pinned to f3058517a1)