{"record":{"id":"44244bfea58c862d","repo":"pentaho/pentaho-kettle","slug":"the-number-of-notes-read","errorCode":null,"errorMessage":"The number of notes read [","messagePattern":"The number of notes read \\[","errorType":"exception","errorClass":"KettleException","httpStatus":null,"severity":"error","filePath":"plugins/pur/core/src/main/java/org/pentaho/di/repository/pur/JobDelegate.java","lineNumber":253,"sourceCode":"      jobMeta.addJobEntry( copy );\n    }\n\n    if ( jobMeta.getJobCopies().size() != nrCopies ) {\n      throw new KettleException( \"The number of job entry copies read [\" + jobMeta.getJobCopies().size()\n          + \"] was not the number we expected [\" + nrCopies + \"]\" );\n    }\n\n    // Read the notes...\n    //\n    DataNode notesNode = rootNode.getNode( NODE_NOTES );\n    int nrNotes = (int) notesNode.getProperty( PROP_NR_NOTES ).getLong();\n    for ( DataNode noteNode : notesNode.getNodes() ) {\n      String xml = getString( noteNode, PROP_XML );\n      jobMeta\n          .addNote( new NotePadMeta( XMLHandler.getSubNode( XMLHandler.loadXMLString( xml ), NotePadMeta.XML_TAG ) ) );\n    }\n    if ( jobMeta.nrNotes() != nrNotes ) {\n      throw new KettleException( \"The number of notes read [\" + jobMeta.nrNotes()\n          + \"] was not the number we expected [\" + nrNotes + \"]\" );\n    }\n\n    // Read the hops...\n    //\n    DataNode hopsNode = rootNode.getNode( NODE_HOPS );\n    int nrHops = (int) hopsNode.getProperty( PROP_NR_HOPS ).getLong();\n    for ( DataNode hopNode : hopsNode.getNodes() ) {\n      String copyFromName = getString( hopNode, JOB_HOP_FROM );\n      int copyFromNr = (int) hopNode.getProperty( JOB_HOP_FROM_NR ).getLong();\n      String copyToName = getString( hopNode, JOB_HOP_TO );\n      int copyToNr = (int) hopNode.getProperty( JOB_HOP_TO_NR ).getLong();\n\n      boolean enabled = true;\n      if ( hopNode.hasProperty( JOB_HOP_ENABLED ) ) {\n        enabled = hopNode.getProperty( JOB_HOP_ENABLED ).getBoolean();\n      }\n","sourceCodeStart":235,"sourceCodeEnd":271,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/plugins/pur/core/src/main/java/org/pentaho/di/repository/pur/JobDelegate.java#L235-L271","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Restore the job from a backup or re-save it from the PDI client to rewrite consistent note nodes.","Inspect the job's notes node in the repository to find missing/duplicate note children.","Align PDI client and Pentaho server versions to eliminate serialization differences.","Delete and re-import the job from a known-good .kjb file.","Catch KettleException in loading code and fall back to re-import or a cached copy of the job."],"exampleFix":"// before\nJobMeta jobMeta = (JobMeta) repository.loadJob(jobId, null).loadAll(); // throws on note-count mismatch\n// after\ntry {\n  jobMeta = (JobMeta) repository.loadJob(jobId, null).loadAll();\n} catch (KettleException e) {\n  if (e.getMessage().startsWith(\"The number of notes read\")) {\n    jobMeta = importJobFromFile(backupKjbPath);\n  } else {\n    throw e;\n  }\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  JobMeta jobMeta = (JobMeta) repository.loadJob(jobId, null).loadAll();\n} catch (KettleException e) {\n  if (e.getMessage().startsWith(\"The number of notes read\")) {\n    // note list inconsistent -> re-import or restore job\n  } else {\n    throw e;\n  }\n}","preventionTips":["Avoid aborted/partial saves; retry failed saves from a clean client state.","Serialize job edits through one client or use repository locking.","Keep versions aligned between PDI and the Pentaho server.","Maintain known-good .kjb exports for restore."],"tags":["pentaho","kettle","repository","corruption","deserialization"],"backgroundTag":"internal-invariant-violation","analyzedSha":"f3058517a153da500bf4551f46d79b91bf8ec552","analyzedAt":"2026-09-13T14:04:16.340Z","contentChangedAt":"2026-09-13T14:04:16.340Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}