pentaho/pentaho-kettle · error · KettleException

The number of notes read [

Error message

The number of notes read [

What it means

After reading note-pad nodes from the stored job DataNode and adding them to jobMeta, JobDelegate verifies jobMeta.nrNotes() equals the expected nrNotes recorded when the job was saved. A mismatch means the note list in the repository is inconsistent with its recorded count, so loading is aborted to avoid silently returning a job with missing (or duplicated) notes.

Solutions

  1. Restore the job from a backup or re-save it from the PDI client to rewrite consistent note nodes.
  2. Inspect the job's notes node in the repository to find missing/duplicate note children.
  3. Align PDI client and Pentaho server versions to eliminate serialization differences.
  4. Delete and re-import the job from a known-good .kjb file.
  5. Catch KettleException in loading code and fall back to re-import or a cached copy of the job.

Example fix

// before
JobMeta jobMeta = (JobMeta) repository.loadJob(jobId, null).loadAll(); // throws on note-count mismatch
// after
try {
  jobMeta = (JobMeta) repository.loadJob(jobId, null).loadAll();
} catch (KettleException e) {
  if (e.getMessage().startsWith("The number of notes read")) {
    jobMeta = importJobFromFile(backupKjbPath);
  } else {
    throw e;
  }
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
  JobMeta jobMeta = (JobMeta) repository.loadJob(jobId, null).loadAll();
} catch (KettleException e) {
  if (e.getMessage().startsWith("The number of notes read")) {
    // note list inconsistent -> re-import or restore job
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Loading a job whose DataNode's NODE_NOTES children count differs from the persisted nrNotes value — typically after a corrupted or partial save, a concurrent writer, or a repository content-serialization version mismatch.

Common situations: Same as job-copy mismatch: failed saves, concurrent PDI clients editing the same job, cross-version import/export of repository content, manual tampering with repository storage.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at plugins/pur/core/src/main/java/org/pentaho/di/repository/pur/JobDelegate.java:253

      jobMeta.addJobEntry( copy );
    }

    if ( jobMeta.getJobCopies().size() != nrCopies ) {
      throw new KettleException( "The number of job entry copies read [" + jobMeta.getJobCopies().size()
          + "] was not the number we expected [" + nrCopies + "]" );
    }

    // Read the notes...
    //
    DataNode notesNode = rootNode.getNode( NODE_NOTES );
    int nrNotes = (int) notesNode.getProperty( PROP_NR_NOTES ).getLong();
    for ( DataNode noteNode : notesNode.getNodes() ) {
      String xml = getString( noteNode, PROP_XML );
      jobMeta
          .addNote( new NotePadMeta( XMLHandler.getSubNode( XMLHandler.loadXMLString( xml ), NotePadMeta.XML_TAG ) ) );
    }
    if ( jobMeta.nrNotes() != nrNotes ) {
      throw new KettleException( "The number of notes read [" + jobMeta.nrNotes()
          + "] was not the number we expected [" + nrNotes + "]" );
    }

    // Read the hops...
    //
    DataNode hopsNode = rootNode.getNode( NODE_HOPS );
    int nrHops = (int) hopsNode.getProperty( PROP_NR_HOPS ).getLong();
    for ( DataNode hopNode : hopsNode.getNodes() ) {
      String copyFromName = getString( hopNode, JOB_HOP_FROM );
      int copyFromNr = (int) hopNode.getProperty( JOB_HOP_FROM_NR ).getLong();
      String copyToName = getString( hopNode, JOB_HOP_TO );
      int copyToNr = (int) hopNode.getProperty( JOB_HOP_TO_NR ).getLong();

      boolean enabled = true;
      if ( hopNode.hasProperty( JOB_HOP_ENABLED ) ) {
        enabled = hopNode.getProperty( JOB_HOP_ENABLED ).getBoolean();
      }

View on GitHub (pinned to f3058517a1)