pentaho/pentaho-kettle · error · org.pentaho.di.core.exception.KettleValueException

KettleValueException wrapping generic Exception while…

Error message

KettleValueException wrapping generic Exception while loading file content (no message)

What it means

The full loadFileContentInBinary deliberately rethrows KettleFileNotFoundException (honoring failIfNoFile), but any OTHER exception while reading the file (VFS IOException, closed stream, encoding errors) is wrapped in a message-less KettleValueException(e). The cause carries the real problem; the message itself is empty.

Solutions

  1. Log/print e.getCause() to get the real underlying IOException
  2. Check file read permissions for the user running the transformation
  3. Validate the VFS URL/scheme and credentials for remote files
  4. Pre-check file.canRead() / exists() before the call

Example fix

// before
Object content = ValueDataUtil.loadFileContentInBinary(bowl, metaA, dataA, true);
// after
try {
  Object content = ValueDataUtil.loadFileContentInBinary(bowl, metaA, dataA, true);
} catch (KettleValueException e) {
  log.error("File content load failed: " + e.getCause(), e);
  throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Java: verify readability before the call
FileObject f = KettleVFS.getFileObject(metaA.getString(dataA));
if (f == null || !f.exists()) throw new FileNotFoundException(...);
if (!f.isReadable()) throw new AccessDeniedException(f.getName().getPath());

Try / catch

try {
  content = ValueDataUtil.loadFileContentInBinary(bowl, metaA, dataA, failIfNoFile);
} catch (KettleValueException e) {
  Throwable cause = e.getCause(); // the real IOException lives here
  log.error("File content load failed: " + (cause == null ? "unknown" : cause.getMessage()), cause);
  throw e;
}

Prevention

When it happens

Trigger: Calling loadFileContentInBinary(bowl, metaA, dataA, failIfNoFile) where the file exists but cannot be read: VFS provider error, permission denied, stream closed, or out-of-memory on huge files.

Common situations: Permission-restricted files in production; VFS misconfiguration (bad scheme/auth for sftp/http files); reading files locked by another process.

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

Appendix: source

Thrown at core/src/main/java/org/pentaho/di/core/row/ValueDataUtil.java:714

    byte[] content = null;
    FileObject file = null;
    InputStream is = null;

    try {
      file = KettleVFS.getInstance( bowl ).getFileObject( dataA.toString() );
      throwsErrorOnFileNotFound( file );
      is = KettleVFS.getInputStream( file );
      int fileSize = (int) file.getContent().getSize();
      content = Const.createByteArray( fileSize );
      is.read( content, 0, fileSize );
    } catch ( KettleFileNotFoundException e ) {
      if ( failIfNoFile ) {
        throw e;
      }
      log.debug( e.getMessage() );
    } catch ( Exception e ) {
      throw new KettleValueException( e );
    } finally {
      IOUtils.closeQuietly( file );
      IOUtils.closeQuietly( is );
    }
    return content;
  }

  public static Object minus( ValueMetaInterface metaA, Object dataA, ValueMetaInterface metaB, Object dataB ) throws KettleValueException {
    if ( dataA == null || dataB == null ) {
      return null;
    }

    switch ( metaA.getType() ) {
      case ValueMetaInterface.TYPE_NUMBER:
        return new Double( metaA.getNumber( dataA ).doubleValue() - metaB.getNumber( dataB ).doubleValue() );
      case ValueMetaInterface.TYPE_INTEGER:
        return new Long( metaA.getInteger( dataA ).longValue() - metaB.getInteger( dataB ).longValue() );
      case ValueMetaInterface.TYPE_BIGNUMBER:

View on GitHub (pinned to f3058517a1)