pentaho/pentaho-kettle · error · KettleException

LDIFInput.Exception.UnableToReadFile

LDIFInput.Exception.UnableToReadFile

Error message

LDIFInput.Exception.UnableToReadFile

What it means

LDIFInput.getOneRow wraps all per-row processing in a catch-all that rethrows as KettleException with message 'Unable to read file' plus the current file name. It fires when any exception occurs while reading/parsing the LDIF file or building the output row. The original exception is chained as the cause, so the real reason (IO error, parse failure, etc.) is in the stack trace.

Solutions

  1. Inspect the chained cause (e.getMessage()/stack trace) for the real underlying failure.
  2. Verify the file still exists and is readable at processing time (ls -l / stat the path).
  3. Re-add the file in the step's file list or fix the wildcard/directory so only valid LDIF files are selected.
  4. If remote (SFTP/HTTP via VFS), check connectivity and credentials.
  5. Re-export or regenerate a corrupt LDIF file and retry.

Example fix

// before: transformation fails at runtime with opaque message
// after: pre-validate files in an earlier step or fix the input list
String path = environmentSubstitute("${INPUT_FILE}");
File f = new File(path);
if (!f.isFile() || !f.canRead()) {
  throw new KettleException("LDIF file missing/unreadable: " + path);
}
Defensive patterns

Strategy: try-catch

Validate before calling

File f = new File(path);
if (!f.isFile() || !f.canRead()) throw new KettleException("Unreadable LDIF file: " + path);

Try / catch

try {
  // run transformation / process row
} catch (KettleException e) {
  Throwable cause = e.getCause();
  log.error("LDIF read failed for file, cause: " + (cause != null ? cause.toString() : "n/a"), e);
  // route row to error handling / skip file
}

Prevention

When it happens

Trigger: getOneRow() processes a row for the current LDIF file (data.file) and any Exception escapes the try block — e.g. VFS cannot open the file, the file stream read fails, or LDIF parsing throws.

Common situations: File deleted or moved between listing and reading; network/remote file (VFS) unreachable; file encoding or malformed LDIF content causes parser exception; permission denied at read time.

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

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/trans/steps/ldifinput/LDIFInput.java:227

      }
      // Add Uri
      if ( meta.getUriField() != null && meta.getUriField().length() > 0 ) {
        outputRowData[rowIndex++] = data.uriName;
      }
      // Add RootUri
      if ( meta.getRootUriField() != null && meta.getRootUriField().length() > 0 ) {
        outputRowData[rowIndex++] = data.rootUriName;
      }
      RowMetaInterface irow = getInputRowMeta();

      data.previousRow = irow == null ? outputRowData : irow.cloneRow( outputRowData ); // copy it to make
      // surely the next step doesn't change it in between...

      incrementLinesInput();
      data.rownr++;

    } catch ( Exception e ) {
      throw new KettleException( BaseMessages.getString( PKG, "LDIFInput.Exception.UnableToReadFile", data.file
        .toString() ), e );
    }

    return outputRowData;
  }

  public boolean processRow( StepMetaInterface smi, StepDataInterface sdi ) throws KettleException {

    Object[] r = null;

    boolean sendToErrorRow = false;
    String errorMessage = null;

    try {
      // Grab one row
      Object[] outputRowData = getOneRow();
      if ( outputRowData == null ) {
        setOutputDone(); // signal end to receiver(s)

View on GitHub (pinned to f3058517a1)