Skip to content

[Proposal] Progressively replace anyhow use in library crates with thiserror #3056

@mitchmindtree

Description

@mitchmindtree

💥 Proposal

While beginning to address #2941 and investigating the feasibility of introducing Result in some locations, I've noticed that anyhow::Result is exposed from the snarkvm_console_network_environment::prelude, and is used throughout a lot of the library crates.

While anyhow can be convenient for not having to think about creating new error types, it is not designed for use within libraries or to be exposed in public APIs.

This is a proposal to remove anyhow::Result from the prelude, and to progressively replace the use of anyhow for error handling throughout the VM libraries with thiserror. I've noticed there is already some use of thiserror which is great!

Motivation

The author of thiserror and anyhow distinguishes between the use-cases for the two crates briefly in the thiserror README:

Use thiserror if you care about designing your own dedicated error type(s) so that the caller receives exactly the information that you choose in the event of failure. This most often applies to library-like code. Use Anyhow if you don't care what error type your functions return, you just want it to be easy. This is common in application-like code.

Problems with anyhow in libraries:

  • Loss of type information: Downstream code cannot match on specific error variants or exhaustively handle different failure modes. Accessing and handling underlying errors requires downcasting which can fail (e.g. can be a problem when refactoring).
  • Poor API boundaries: anyhow::Error is essentially Box<dyn Error> - it's meant for applications that just propagate errors to users, not libraries that need to expose errors as part of their public API.
  • Documentation gaps: Error variants aren't visible in generated docs, leaving users guessing about the set of possible failure modes. Ideally, a user can read the error type returned within the Result and see all possible failure modes for the API their calling.

Benefits of thiserror in libraries:

  • Concrete error enums that can be matched and handled exhaustively in a type-safe manner (i.e. no downcasting required).
  • Library users can see the full set of possible failure modes just by looking at the error type.
  • Proper error composition through transparent wrapping of underlying errors.

Having nice error types would be great for consumers of the snarkvm libs (like leo tooling) so that we can handle different error variants accordingly (e.g. handling a VM halt vs some deployment failure).

Implementation

This might look something like:

  • Remove anyhow::Result from snarkvm_console_network_environment::prelude so that it no longer overrides the Result type from the std prelude.
  • When introducing new errors, use thiserror to declare concrete types.
  • Temporarily provide a Anyhow variant in concrete error types where necessary as a temporarily workaround?
  • Open a tracking issue for replacing all anyhow use within libraries with dedicated error types/variants (could be a good issue for juniors or newcomers).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions