Skip to content

[ntuple] Throw informative error when collection proxy dictionary is missing (#21274) - #23766

Open
ishaaaan17 wants to merge 1 commit into
root-project:masterfrom
ishaaaan17:fix/rntuple-missing-dict-error
Open

ishaaaan17 wants to merge 1 commit into
root-project:masterfrom
ishaaaan17:fix/rntuple-missing-dict-error

Conversation

@ishaaaan17

Copy link
Copy Markdown
Contributor

summary of changes

fixes #21274.

when an RNTuple collection proxy field (for example std::set or std::map) was created for a type that has no dictionary, ROOT hit an assertion failure in TGenCollectionProxy.cxx:401 (R__ASSERT(e->IsValid())), or failed while inspecting the collection proxy.

this change:

  1. checks classp->HasDictionary() in the constructor of RProxiedCollectionField, before the collection proxy is generated, and throws a ROOT::RException with the name of the missing type ("<type> has no dictionary entry available").
  2. adds a unit test in tree/ntuple/test/ntuple_types.cxx under TEST(RNTuple, TVirtualCollectionProxy). it checks that a collection type without a loaded dictionary (std::map<double, double>) throws a ROOT::RException with this error message.

checklist

  • code style checked with .clang-format
  • unit test added
  • follows the minimal diff guidelines (12 lines added, 0 deleted)

ai disclosure

Assisted-by: antigravity:gemini. i used an ai assistant to follow the collection proxy generation call stack in RProxiedCollectionField and TGenCollectionProxy. i checked the dictionary lookup against TClass::HasDictionary(), wrote the unit test and the exception check, and checked the formatting with .clang-format.

@jblomer jblomer left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In principle looks good to me.

Comment on lines +1332 to 1337
// Proxied collections require a compiled dictionary for C++ iterators and element types.
// Eagerly check here to avoid low-level assertion failures or segfaults during proxy inspection (issue #21274).
if (!classp->HasDictionary())
throw RException(R__FAIL(std::string(classp->GetName()) + " has no dictionary entry available"));
if (!classp->GetCollectionProxy())
throw RException(R__FAIL(std::string(classp->GetName()) + " has no associated collection proxy"));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Swap these two conditions.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done @jblomer! i swapped the two checks, so GetCollectionProxy() is checked first and then HasDictionary(). thanks!

@ishaaaan17
ishaaaan17 force-pushed the fix/rntuple-missing-dict-error branch from 16d0d8a to ac5db1b Compare October 21, 2026 22:08
// Eagerly check here to avoid low-level assertion failures or segfaults during proxy inspection (issue #21274).
if (!classp->GetCollectionProxy())
throw RException(R__FAIL(std::string(classp->GetName()) + " has no associated collection proxy"));
if (!classp->HasDictionary())

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This condition in itself might be too strict. In particular for the case of std::pair, we only need to have its 2 argument to have a dictionary (or be a pair).

Related, if emulated collection proxy are supported here, the underlying line type would not have a dictionary.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correcting myself, the test is not on the containee but on the container. It has the side effect (intentional or not) of prevent the use of emulated collection proxy.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for the note @pcanal!

yes, it is intentional that RProxiedCollectionField does not allow emulated collection proxies. RProxiedCollectionField depends on compiled iterator function pointers (proxy->GetFunctionCreateIterators(), etc., in RCollectionIterableOnce::GetIteratorFuncs, line 1322), and these are not available for emulated collection proxies.

for on-disk collections that have no compiled dictionary, RNTuple reads them as untyped emulated vector fields (CreateEmulatedVectorField) and not through RProxiedCollectionField.

@ishaaaan17
ishaaaan17 requested a review from pcanal October 22, 2026 02:46

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[ntuple] ROOT crashes when type info of collection proxy-based fields is not available

4 participants