Gracefully skip missing branches in TDataFrame.Snapshot

When tying to write a snapshot of a TDataFrame, one can pass a list of branch names to write out. If, either due to a misspelling or another bug, one of these branches does not exist, the stack trace is quite long and hard to read:

 *** Break *** segmentation violation



===========================================================
There was a crash.
This is the entire stack trace of all threads:
===========================================================
#0  0x00007fde2b57145a in __GI___waitpid (pid=30774, stat_loc=stat_loc
entry=0x7ffc51377bc0, options=options
entry=0) at ../sysdeps/unix/sysv/linux/waitpid.c:29
#1  0x00007fde2b4ea2cb in do_system (line=<optimized out>) at ../sysdeps/posix/system.c:148
#2  0x00007fde2c0f4288 in TUnixSystem::Exec (shellcmd=<optimized out>, this=0x55a32f19f4f0) at /cern/root-git2/core/unix/src/TUnixSystem.cxx:2118
#3  TUnixSystem::StackTrace (this=0x55a32f19f4f0) at /cern/root-git2/core/unix/src/TUnixSystem.cxx:2412
#4  0x00007fde2c0f68ec in TUnixSystem::DispatchSignals (this=0x55a32f19f4f0, sig=kSigSegmentationViolation) at /cern/root-git2/core/unix/src/TUnixSystem.cxx:3643
#5  <signal handler called>
#6  ROOT::Internal::TDF::ColumnName2ColumnTypeName (colName="Z0_TRUEID", tree=..., tmpBranch=0x0) at /cern/root-git2/tree/treeplayer/src/TDFUtils.cxx:65
#7  0x00007fde1e50a67e in ROOT::Experimental::TDF::TInterface<ROOT::Detail::TDF::TFilterBase>::Snapshot (this=<optimized out>, treename="DYTuple/DecayTree", filename="test_reduced.root", bnames=std::vector of length 51, capacity 51 = {...}) at /cern/root-build/include/ROOT/TDFInterface.hxx:274
#8  0x00007fde1b88ed68 in reduce_df(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) () from /home/andreas/cernbox/work/drell-yan/scripts/reduce_df_cxx.so
#9  0x00007fde2c8180e7 in ?? ()
#10 0x000055a33206a170 in ?? ()
#11 0x000000000000001d in ?? ()
#12 0x000000000000001d in ?? ()
#13 0x00007ffc5137b450 in ?? ()
#14 0x00007ffc5137b480 in ?? ()
#15 0x00007fde2c818070 in ?? ()
#16 0x00007ffc5137b4a0 in ?? ()
#17 0x00007fde27262197 in cling::Interpreter::RunFunction(clang::FunctionDecl const*, cling::Value*) [clone .part.282] () from /cern/root-build/lib/libCling.so
#18 0x00007fde2726588d in cling::Interpreter::EvaluateInternal(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, cling::CompilationOptions, cling::Value*, cling::Transaction**, unsigned long) () from /cern/root-build/lib/libCling.so
#19 0x00007fde27265a92 in cling::Interpreter::process(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, cling::Value*, cling::Transaction**, bool) () from /cern/root-build/lib/libCling.so
#20 0x00007fde272f1e2f in cling::MetaProcessor::process(char const*, cling::Interpreter::CompilationResult&, cling::Value*, bool) () from /cern/root-build/lib/libCling.so
#21 0x00007fde271ec919 in HandleInterpreterException (metaProcessor=<optimized out>, input_line=<optimized out>, compRes=
0x7ffc5137b804: cling::Interpreter::kSuccess, result=result
entry=0x7ffc5137b810) at /cern/root-git2/core/metacling/src/TCling.cxx:1887
#22 0x00007fde271fd464 in TCling::ProcessLine (this=0x55a32f1f9c70, line=<optimized out>, error=0x7ffc5137c96c) at /cern/root-git2/core/metacling/src/TCling.cxx:2009
#23 0x00007fde271ef85d in TCling::ProcessLineSynch (this=0x55a32f1f9c70, line=0x55a32fca56b0 ".X  /home/andreas/cernbox/work/drell-yan/scripts/./reduce_df.cxx++(\"../ntuple/dy_tuple_12_md.root\")", error=0x7ffc5137c96c) at /cern/root-git2/core/metacling/src/TCling.cxx:2886
#24 0x00007fde2bfd4da7 in TApplication::ExecuteFile (file=<optimized out>, error=0x7ffc5137c96c, keep=<optimized out>) at /cern/root-git2/core/base/src/TApplication.cxx:1137
#25 0x00007fde2bfd6b53 in TApplication::ProcessLine (this=0x55a32f1eaad0, line=<optimized out>, sync=<optimized out>, err=0x7ffc5137c96c) at /cern/root-git2/core/base/src/TApplication.cxx:982
#26 0x00007fde2c4127e4 in TRint::ProcessLineNr (this=this
entry=0x55a32f1eaad0, filestem=filestem
entry=0x7fde2c423f4c "ROOT_cli_", line=line
entry=0x7ffc5137c970 ".x reduce_df.cxx++(\"../ntuple/dy_tuple_12_md.root\")", error=error
entry=0x7ffc5137c96c) at /cern/root-git2/core/rint/src/TRint.cxx:756
#27 0x00007fde2c413db7 in TRint::Run (this=0x55a32f1eaad0, retrn=<optimized out>) at /cern/root-git2/core/rint/src/TRint.cxx:416
#28 0x000055a32df04dbc in main (argc=<optimized out>, argv=0x7ffc5137eaf8) at /cern/root-git2/main/src/rmain.cxx:30
===========================================================


The lines below might hint at the cause of the crash.
You may get help by asking at the ROOT forum http://root.cern.ch/forum.
Only if you are really convinced it is a bug in ROOT then please submit a
report at http://root.cern.ch/bugs. Please post the ENTIRE stack trace
from above as an attachment in addition to anything else
that might help us fixing this issue.
===========================================================
#6  ROOT::Internal::TDF::ColumnName2ColumnTypeName (colName="Z0_TRUEID", tree=..., tmpBranch=0x0) at /cern/root-git2/tree/treeplayer/src/TDFUtils.cxx:65
#7  0x00007fde1e50a67e in ROOT::Experimental::TDF::TInterface<ROOT::Detail::TDF::TFilterBase>::Snapshot (this=<optimized out>, treename="DYTuple/DecayTree", filename="test_reduced.root", bnames=std::vector of length 51, capacity 51 = {...}) at /cern/root-build/include/ROOT/TDFInterface.hxx:274
#8  0x00007fde1b88ed68 in reduce_df(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) () from /home/andreas/cernbox/work/drell-yan/scripts/reduce_df_cxx.so
#9  0x00007fde2c8180e7 in ?? ()
#10 0x000055a33206a170 in ?? ()
#11 0x000000000000001d in ?? ()
#12 0x000000000000001d in ?? ()
#13 0x00007ffc5137b450 in ?? ()
#14 0x00007ffc5137b480 in ?? ()
#15 0x00007fde2c818070 in ?? ()
#16 0x00007ffc5137b4a0 in ?? ()
#17 0x00007fde27262197 in cling::Interpreter::RunFunction(clang::FunctionDecl const*, cling::Value*) [clone .part.282] () from /cern/root-build/lib/libCling.so
#18 0x00007fde2726588d in cling::Interpreter::EvaluateInternal(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, cling::CompilationOptions, cling::Value*, cling::Transaction**, unsigned long) () from /cern/root-build/lib/libCling.so
#19 0x00007fde27265a92 in cling::Interpreter::process(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, cling::Value*, cling::Transaction**, bool) () from /cern/root-build/lib/libCling.so
#20 0x00007fde272f1e2f in cling::MetaProcessor::process(char const*, cling::Interpreter::CompilationResult&, cling::Value*, bool) () from /cern/root-build/lib/libCling.so
#21 0x00007fde271ec919 in HandleInterpreterException (metaProcessor=<optimized out>, input_line=<optimized out>, compRes=
0x7ffc5137b804: cling::Interpreter::kSuccess, result=result
entry=0x7ffc5137b810) at /cern/root-git2/core/metacling/src/TCling.cxx:1887
===========================================================

The current ROOT functions usually ignore if a branch does not exist (for example TTree.SetBranchStatus):

Attaching file ../ntuple/dy_tuple_12_md_reduced.root as _file0...
(TFile *) 0x5582b83bcde0
root [1] auto t = (TTree*) _file0->Get("DYTuple/DecayTree")
(TTree *) 0x5582b87a75d0
root [2] t->SetBranchStatus("asdf", kTRUE)
Error in <TTree::SetBranchStatus>: unknown branch -> asdf
root [4]

An error is displayed, but it is recovered. The same thing would be nice here.

This has the usecase when using the same selection program for MC and data events. The MC ntuples has some additional branches (like the TRUEID of the particles), which the data lacks. Of course, the alternative is to change the list of branches when processing a MC file, but it would be nice to have it fail more gracefully than with a cryptic stack trace without any clear reason (it becomes quite obvious when looking at the first line of the stack trace what the problem is, though: ROOT::Internal::TDF::ColumnName2ColumnTypeName (colName="Z0_TRUEID", tree=..., tmpBranch=0x0) a)

Hi,
thank you, this is already on the TODO list.
The intention is throwing an exception in case a branch does not exist.
Ideally one could catch it and keep going as if you never called that method on TDataFrame.
It’s in the works :slight_smile:

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.

Follow-up: the master branch – and soon v6.10-02 – now throws an exception with a readable message instead of crashing violently in cases like this.

2 Likes