{"record":{"id":"086393db459d343f","repo":"pentaho/pentaho-kettle","slug":"the-number-of-notes-read-notes-was-not-the-number-we","errorCode":null,"errorMessage":"The number of notes read [${notes}] was not the number we expected [${expected}]","messagePattern":"The number of notes read \\[(.+?)\\] was not the number we expected \\[(.+?)\\]","errorType":"exception","errorClass":"KettleException","httpStatus":null,"severity":"error","filePath":"plugins/pur/core/src/main/java/org/pentaho/di/repository/pur/TransDelegate.java","lineNumber":416,"sourceCode":"    for ( int i = 0; i < transMeta.nrSteps(); i++ ) {\n      StepMeta stepMeta = transMeta.getStep( i );\n      StepMetaInterface sii = stepMeta.getStepMetaInterface();\n      if ( sii != null ) {\n        sii.searchInfoAndTargetSteps( transMeta.getSteps() );\n      }\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      transMeta\n          .addNote( new NotePadMeta( XMLHandler.getSubNode( XMLHandler.loadXMLString( xml ), NotePadMeta.XML_TAG ) ) );\n    }\n    if ( transMeta.nrNotes() != nrNotes ) {\n      throw new KettleException( \"The number of notes read [\" + transMeta.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 stepFromName = getString( hopNode, TRANS_HOP_FROM );\n      String stepToName = getString( hopNode, TRANS_HOP_TO );\n      boolean enabled = true;\n      if ( hopNode.hasProperty( TRANS_HOP_ENABLED ) ) {\n        enabled = hopNode.getProperty( TRANS_HOP_ENABLED ).getBoolean();\n      }\n\n      StepMeta stepFrom = StepMeta.findStep( transMeta.getSteps(), stepFromName );\n      StepMeta stepTo = StepMeta.findStep( transMeta.getSteps(), stepToName );\n","sourceCodeStart":398,"sourceCodeEnd":434,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/plugins/pur/core/src/main/java/org/pentaho/di/repository/pur/TransDelegate.java#L398-L434","documentation":"TransDelegate.dataNodeToElement rebuilds a TransMeta from a stored DataNode and counts the note (NotepadMeta) nodes it expects, then verifies transMeta.nrNotes() matches. If adding notes produced a different count than the stored node count, this KettleException is thrown, indicating the stored transformation data is inconsistent or notes were rejected during load.","triggerScenarios":"Loading a transformation from the PUR repository where the number of note nodes under NODE_NOTES differs from the resulting TransMeta note count — e.g., duplicate/invalid note XML causes addNote to skip or the stored data was modified out-of-band.","commonSituations":"Manually edited repository content in the Jackrabbit backend, imports/export round-trips that lost or duplicated notes, corrupted transformation nodes, or version mismatches between writer and reader.","solutions":["Re-export/re-save the transformation from a working copy so its notes are re-serialized consistently.","Inspect the stored NODE_NOTES data (PROP_XML of each note) for corrupt or duplicate entries.","Compare the stored note count with the loaded count from the exception message to locate the discrepant note.","Restore the transformation from a previous repository version."],"exampleFix":"// before\nDataNode noteNode : notesNode.getNodes() -> addNote( ... ); // count mismatch thrown\n// after\nfor ( DataNode noteNode : notesNode.getNodes() ) {\n  String xml = getString( noteNode, PROP_XML );\n  if ( xml == null || xml.isEmpty() ) {\n    log.logBasic( \"Skipping empty note XML in transformation \" + transMeta.getName() );\n    continue; // and adjust expected nrNotes accordingly\n  }\n  transMeta.addNote( new NotePadMeta( XMLHandler.getSubNode( XMLHandler.loadXMLString( xml ), NotePadMeta.XML_TAG ) ) );\n}","handlingStrategy":"try-catch","validationCode":"int storedNotes = notesNode.getNodes().size();\n// after load: transMeta.nrNotes() must equal storedNotes","typeGuard":null,"tryCatchPattern":"try {\n  delegate.dataNodeToElement( node, transMeta );\n} catch ( KettleException e ) {\n  if ( e.getMessage().contains( \"number of notes read\" ) ) {\n    logError( \"Corrupt transformation data; restoring previous version\" );\n    restorePreviousVersion( transMeta.getObjectId() );\n  } else { throw e; }\n}","preventionTips":["Don't manually edit repository backend data","Restore transformations from version history when load integrity checks fail","Keep Kettle versions consistent between writer and reader","Re-save transformations after repository imports"],"tags":["repository","transformation","data-integrity","pentaho-kettle"],"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"}