pentaho/pentaho-kettle · error · KettleException

AvroInput.Error.ObjectReadError

Error message

AvroInput.Error.ObjectReadError

What it means

While reading the next record from an Avro container (Object Container File) via DataFileReader, an IOException occurred. AvroNestedReader wraps it in a KettleException with this generic 'object read error' message, dropping the underlying cause details from the user-visible message.

Solutions

  1. Check the full stack trace/cause for the underlying IOException (file system error vs decode error).
  2. Re-transfer or regenerate the Avro container file; validate with avro-tools (e.g. getfilemeta / tojson).
  3. Confirm read permissions and stable connectivity if the file is on a remote/VFS location.
  4. Verify the file was produced by a compatible Avro version and not truncated (compare checksums).
Defensive patterns

Strategy: try-catch

Try / catch

try {
  rows = reader.avroObjectToKettle(row, space);
} catch (KettleException e) {
  if (e.getCause() instanceof IOException) { log("container read failed", e.getCause()); retryOrAbort(); } else throw e;
}

Prevention

When it happens

Trigger: m_containerReader.next(...) or hasNext() throws IOException inside avroObjectToKettle — corrupt/truncated container file, sync-marker mismatch, or I/O error on the underlying stream.

Common situations: Partially transferred or truncated .avro files; files corrupted in transit; network/permission failures mid-read from remote VFS locations; Avro writer version producing blocks the reader cannot decode.

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

Appendix: source

Thrown at plugins/avro-format/core/src/main/java/org/pentaho/di/trans/steps/avro/input/AvroNestedReader.java:1450

            // special case for top-level record. In case we actually
            // have a top level union, reassign the record so that
            // we have the correctly populated object in the case
            // where our last record instance can't be reused (i.e.
            // the next record read is a different one from the union
            // than the last one).
            m_topLevelRecord = (GenericData.Record) m_containerReader.next( m_topLevelRecord );
          } else if ( m_topLevelArray != null ) {
            m_containerReader.next( m_topLevelArray );
          } else {
            m_containerReader.next( m_topLevelMap );
          }

          return setKettleFields( incoming, space );
        } else {
          return null; // no more input
        }
      } catch ( IOException e ) {
        throw new KettleException( BaseMessages
          .getString( PKG, "AvroInput.Error.ObjectReadError" ) );
      }
    } else {
      // non-container file
      try {
        /*
         * if (m_decoder.isEnd()) { return null; }
         */

        // reading from an incoming field
        if ( m_decodingFromField ) {
          if ( incoming == null || incoming.length == 0 ) {
            // must be done - just return null
            return null;
          }
          ValueMetaInterface fieldMeta = m_incomingRowMeta.getValueMeta( m_fieldToDecodeIndex );

          // incoming avro field null? - all decoded fields are null

View on GitHub (pinned to f3058517a1)