Using context.unrestrictedTraverse to a non-existant path raises KeyError

This surprised me. Why does traversing to a non existing path raise a KeyError and not a TraversalError?

(Pdb++) navroot.unrestrictedTraverse('blabla')
*** KeyError: 'blabla'
Traceback (most recent call last):
  File "/Users/fred/.buildout/eggs/Zope-4.1.3-py3.7.egg/OFS/Traversable.py", line 350, in unrestrictedTraverse
    raise e
  File "/Users/fred/.buildout/eggs/Zope-4.1.3-py3.7.egg/OFS/Traversable.py", line 301, in unrestrictedTraverse
    next = obj[name]
  File "/Users/fred/.buildout/eggs/Zope-4.1.3-py3.7.egg/OFS/ObjectManager.py", line 837, in __getitem__
    raise KeyError(key)

Even more interesting things happen when you try to navigation to a browser view and you make a typo:

(Pdb++) navroot.unrestrictedTraverse('@@overview-controlpanel')
<Products.Five.browser.metaconfigure.OverviewControlPanel object at 0x10c459490>
navroot.unrestrictedTraverse('@@overview_controlpanel')
*** AttributeError: @@overview_controlpanel
Traceback (most recent call last):
  File "/Users/fred/.buildout/eggs/Zope-4.1.3-py3.7.egg/OFS/Traversable.py", line 237, in unrestrictedTraverse
    ns, nm, obj, aq_acquire(self, 'REQUEST'))
  File "/Users/fred/.buildout/eggs/zope.traversing-4.3.1-py3.7.egg/zope/traversing/namespace.py", line 165, in namespaceLookup
    return traverser.traverse(name, ())
  File "/Users/fred/.buildout/eggs/Products.CMFPlone-5.2.1-py3.7.egg/Products/CMFPlone/earlypatches/security.py", line 15, in traverse
    return old_traverse(self, name, ignored)
  File "/Users/fred/.buildout/eggs/zope.traversing-4.3.1-py3.7.egg/zope/traversing/namespace.py", line 421, in traverse
    raise LocationError(self.context, name)
zope.location.interfaces.LocationError: (<PloneSite at /plone>, 'overview_controlpanel')

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/fred/.buildout/eggs/Zope-4.1.3-py3.7.egg/OFS/Traversable.py", line 350, in unrestrictedTraverse
    raise e
  File "/Users/fred/.buildout/eggs/Zope-4.1.3-py3.7.egg/OFS/Traversable.py", line 244, in unrestrictedTraverse
    raise AttributeError(name)

I get a LocationError / AttributeError.

That is because a TraversalError is raised by zope.traversing, which is used only for publishing objects, not object traversal in code.

https://docs.plone.org/develop/plone/serving/traversing.html#custom-traversal

Plone Foundation Code of Conduct