pentaho/pentaho-kettle · error · java.lang.RuntimeException

Error serializing row to byte array

Error message

Error serializing row to byte array

What it means

RowMeta.createOriginalRow/serialization helper wraps any exception raised while writing a row's binary representation (metadata.writeData on a DataOutputStream) into a RuntimeException. The library throws it because binary row serialization is used in clustering/step-internal transport and any failure means the row cannot be transmitted. The original exception is preserved as the cause.

Solutions

  1. Inspect the cause (e.getCause()) to find which value/meta failed to serialize
  2. Verify each Object[] value matches the declared type in RowMeta (Integer for TYPE_INTEGER, Long where required, etc.)
  3. Rebuild the RowMeta from a real data source instead of hand-crafting it
  4. Check that producer and consumer steps use the same Pentaho/Kettle version

Example fix

// before
RowMetaInterface meta = ...; meta.addValueMeta(new ValueMetaString("f"));
byte[] b = RowMeta.getData(meta, new Object[]{ 42 }); // Long into string meta
// after
byte[] b = RowMeta.getData(meta, new Object[]{ "42" }); // value matches meta type
Defensive patterns

Strategy: try-catch

Validate before calling

// Java: validate values match meta before serializing
for (int i = 0; i < meta.size(); i++) {
  ValueMetaInterface vm = meta.getValueMeta(i);
  Object v = row[i];
  if (v != null) {
    Class<?> expect = vm.getNativeDataTypeClass();
    if (expect != null && !expect.isInstance(v))
      throw new IllegalArgumentException("Field " + vm.getName() + " expects " + expect + " but got " + v.getClass());
  }
}

Type guard

boolean matchesMeta(ValueMetaInterface vm, Object v) {
  if (v == null) return true;
  Class<?> expect = vm.getNativeDataTypeClass();
  return expect == null || expect.isInstance(v);
}

Try / catch

try {
  byte[] data = RowMeta.getData(meta, row);
} catch (RuntimeException e) {
  Throwable cause = e.getCause();
  throw new IllegalStateException("Row serialization failed: " + cause.getMessage(), cause);
}

Prevention

When it happens

Trigger: Calling RowMeta.getData() (serialize row to byte[]) when a value in the row cannot be written by its ValueMeta (e.g. corrupt or mismatched value object for the declared type), or an I/O error on the underlying ByteArrayOutputStream (rare).

Common situations: Rows built manually with values not matching their ValueMeta types; custom ValueMeta implementations with broken writeData; serialization across kettle versions where the binary format changed.

Understand the failure class

Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.

Related errors


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

Appendix: source

Thrown at core/src/main/java/org/pentaho/di/core/row/RowMeta.java:1130

  }

  /**
   * Serialize a row of data to byte[]
   *
   * @param metadata the metadata to use
   * @param row      the row of data
   * @return a serialized form of the data as a byte array
   */
  public static byte[] extractData( RowMetaInterface metadata, Object[] row ) {
    try {
      ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
      DataOutputStream dataOutputStream = new DataOutputStream( byteArrayOutputStream );
      metadata.writeData( dataOutputStream, row );
      dataOutputStream.close();
      byteArrayOutputStream.close();
      return byteArrayOutputStream.toByteArray();
    } catch ( Exception e ) {
      throw new RuntimeException( "Error serializing row to byte array", e );
    }
  }

  /**
   * Create a row of data bases on a serialized format (byte[])
   *
   * @param data     the serialized data
   * @param metadata the metadata to use
   * @return a new row of data
   */
  public static Object[] getRow( RowMetaInterface metadata, byte[] data ) {
    try {
      ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream( data );
      DataInputStream dataInputStream = new DataInputStream( byteArrayInputStream );
      return metadata.readData( dataInputStream );
    } catch ( Exception e ) {
      throw new RuntimeException( "Error de-serializing row of data from byte array", e );
    }

View on GitHub (pinned to f3058517a1)