@@ -286,6 +286,21 @@ int main(int argc, char* argv[])
286286 }
287287 outputDir->cd ();
288288 auto outputTree = inputTree->CloneTree (-1 , (fastCopy) ? " fast" : " " );
289+ // Validate that all branches have the same number of entries after CloneTree.
290+ // Fast copy from remote (xrootd) sources can silently produce corrupt trees
291+ // if a read fails mid-transfer.
292+ {
293+ auto expectedEntries = outputTree->GetEntries ();
294+ TObjArray* clonedBranches = outputTree->GetListOfBranches ();
295+ for (int ib = 0 ; ib < clonedBranches->GetEntriesFast (); ++ib) {
296+ auto * br = (TBranch*)clonedBranches->UncheckedAt (ib);
297+ if (br->GetEntries () != expectedEntries) {
298+ printf (" *** FATAL ***: After CloneTree, branch %s has %lld entries but tree has %lld\n " ,
299+ br->GetName (), br->GetEntries (), expectedEntries);
300+ exitCode = 7 ;
301+ }
302+ }
303+ }
289304 currentDirSize += inputTree->GetTotBytes (); // NOTE outputTree->GetTotBytes() is 0, so we use the inputTree here
290305 alreadyCopied = true ;
291306 outputTree->SetAutoFlush (0 );
@@ -308,6 +323,7 @@ int main(int argc, char* argv[])
308323 // detect VLA
309324 if (((TLeaf*)br->GetListOfLeaves ()->First ())->GetLeafCount () != nullptr ) {
310325 int maximum = ((TLeaf*)br->GetListOfLeaves ()->First ())->GetLeafCount ()->GetMaximum ();
326+ maximum = std::max (maximum, 1 );
311327
312328 // get type
313329 static TClass* cls;
@@ -477,4 +493,4 @@ int main(int argc, char* argv[])
477493 printf (" \n " );
478494
479495 return exitCode;
480- }
496+ }
0 commit comments