`Exn<T>` preserves the outmost error type and `Exn::<T>::as_error()` will give you the error just the way you want.
Traversing though the error tree is the worst case where the structured error has been bubbled up through layers until the one who are able to recover from it.
That worst case shouldn't happen. When you do something like this:
you're burying the error thrown by `serialize(&doc)` in such a way that you have to dig for it dynamically to recover it.The closure in `or_raise` should take the error from `serialize(&doc)` as an argument and save the actionable details. It makes sense to have an "outermost error" when you're talking about a context trace that provides information to humans, but an error which a machine responds to should be flat & statically matchable.
Something like this:
where `StorageError::fromInner` decides whether the error should be permanent or not based on the contents of `e`, and saves any details that would be relevant for automatically recovering from the error.