Good suggestions. I don't like the part about embedding lower level errors as strings through since that makes it much harder to automatically process the error.
One problem is that Rust doesn't support tagged unions. enum is regrettably solving a different problem, but since it's the only hammer we have, it's abused for this kind of thing. This often leads to having to write match error ... unreachable.
Error handling was kind of a pain to wrap my head around within the Rust Ecosystem, between the different crates, custom enums and learning about Box<dyn Error>. I do enjoy errors now that I understand how the community is using them a little better, and the idea of there being one control flow with errors being a possible 'result'.
Author seems to have some good experience composing errors in Rust applications... good read!