Thirty-Second Error Review
You can assess a module’s error handling from its types, before reading any bodies:
| You see | Likely conclusion |
|---|---|
Result<T, ModuleError> with a dedicated enum | The failure modes were designed. |
| An opaque error type in application code | A reasonable default. Check that context is attached at boundaries. |
| An opaque error type in a library API | Callers can’t match on failures. Flag it. |
Result<T, String> | The error path wasn’t designed. |
-> T with unwrap() or expect() inside | Read the messages. A panic on a documented invariant is a contract; a panic on input is a failure path hidden as a crash. |
| Several of the above in one crate | Modules were generated separately with no shared convention. |
The last row is the most characteristic of generated codebases. In that case the inconsistency is the main finding: one convention applied uniformly is easier to review than a mixture of individually good ones.
The prompt that fixes a poorly graded module is usually structural:
“define one XError enum for this module, implementing
std::error::Error; convert all String and boxed-error returns to it, and attach context at each
? that crosses a module boundary.”