Skip to content

Conversation

@fitzgen
Copy link
Member

@fitzgen fitzgen commented Dec 29, 2025

Instead of anyhow::Error.

This commit re-exports wasmtime_environ::error as the wasmtime::error module, updates the prelude to include these new error-handling types, redirects our top-level wasmtime::{Error, Result} re-exports to re-export wasmtime::error::{Error, Result}, and updates various use sites that were directly using anyhow to use the new wasmtime versions.

This process also required updating the component macro and wit-bindgen macro to use the new error types instead of anyhow.

Part of #12069

@fitzgen fitzgen requested a review from alexcrichton December 29, 2025 22:04
@fitzgen fitzgen requested review from a team as code owners December 29, 2025 22:04
@fitzgen fitzgen force-pushed the migrate-wasmtime-to-wasmtime-error branch from a6c7162 to 9b06a14 Compare December 29, 2025 22:06
Instead of `anyhow::Error`.

This commit re-exports the `wasmtime_environ::error` as the `wasmtime::error`
module, updates the prelude to include these new error-handling types, redirects
our top-level `wasmtime::{Error, Result}` re-exports to re-export
`wasmtime::error::{Error, Result}`, and updates various use sites that were
directly using `anyhow` to use the new `wasmtime` versions.

This process also required updating the component macro and wit-bindgen macro to
use the new error types instead of `anyhow`.

Part of bytecodealliance#12069
@fitzgen fitzgen force-pushed the migrate-wasmtime-to-wasmtime-error branch from 9b06a14 to 0b4fae7 Compare December 29, 2025 22:08
@fitzgen fitzgen changed the title Migrate the wasmtime crate to wasmtime_internal_error::Error Migrate the wasmtime crate to wasmtime_environ::error::* Dec 29, 2025
@alexcrichton
Copy link
Member

In retrospect, should we bother with wasmtime::error as a module? (vs just having reexports at the top). I would expect almost all uses to go through wasmtime::Result instead of wasmtime::error::Result (and is something I'd ideally like to see changed in the bindgen output for example).

@fitzgen
Copy link
Member Author

fitzgen commented Jan 5, 2026

In retrospect, should we bother with wasmtime::error as a module?

I think we do want a module because otherwise we would have wasmtime::Context (instead of wasmtime::error::Context) which is pretty ambiguous with StoreContext and all that (and we also don't want to rename Context because we want to continue to have porting to the new error infra be just flipping the switch from anyhow to wasmtime-internal-error, which requires API compatibility).

@fitzgen
Copy link
Member Author

fitzgen commented Jan 5, 2026

(and is something I'd ideally like to see changed in the bindgen output for example).

Happy to change it, but also this seems like it shouldn't really matter since it is just in macro-expanded code?

@alexcrichton
Copy link
Member

Scattered thought from some more review:

  • Migration is happening in incremental steps, so renaming Context to ErrorContext isn't out of the question is it? For example nothing is using wasmtime::Context today or expecting that to work, so having users change anyhow::Context to wasmtime::ErrorContext doesn't seem like a deal-breaker.
  • It's true yeah that macro-expanded code doesn't matter much, but having two paths to the same type means that it's inevitably going to be used both ways in different places. There are other files modified here which use crate::error::... instead of crate::... for example.
  • Personally I think that error-handling ergonomics are of a pretty high importance so I want to make sure we're not losing anything in this transition. It's quite easy to throw anyhow::Foo somewhere for example but wasmtime:::error::Foo is much more of a mouthful already. That's where I'd like to keep everything at the crate root of wasmtime::Foo if we can. That's already still slightly worse than anyhow due to the crate name being longer, but there's not much we can do about that. On example is anyhow::Ok(...) being migrated here to wasmtime::error::Ok(...) in a few places which feels overkill to me in terms of "here's a quick type annotation" which has turned into a much longer type annotation

@fitzgen
Copy link
Member Author

fitzgen commented Jan 5, 2026

Migration is happening in incremental steps, so renaming Context to ErrorContext isn't out of the question is it? For example nothing is using wasmtime::Context today or expecting that to work, so having users change anyhow::Context to wasmtime::ErrorContext doesn't seem like a deal-breaker.

I would say it is 100% a deal-breaker for existing projects that already embed Wasmtime, currently use anyhow, and will start using wasmtime::Error instead. As long as they are only using anyhow via the wasmtime::{Error, Result} aliases today, then the upgrade to Wasmtime that switches away from anyhow shouldn't involve changing any code at all. But if they are using anyhow directly, for example to get the Context trait in scope, then they should be able to mechanically replace all anyhow::Foo with wasmtime::error::Foo. The more things we change, the more pain we are causing downstream.

Personally I think that error-handling ergonomics are of a pretty high importance so I want to make sure we're not losing anything in this transition.

I agree, which is why I am focusing on not only the Wasmtime developers' ergonomics but also embedders' ergonomics. The best ergonomics is "you don't need to change anything in your existing code and you're already familiar with all the APIs" which is what we get with matching anyhow's API and have been aiming for this whole time.

On example is anyhow::Ok(...) being migrated here to wasmtime::error::Ok(...) in a few places which feels overkill to me in terms of "here's a quick type annotation" which has turned into a much longer type annotation

This is actually another example of why we cannot just export everything at the top level. A ton of our code in examples, tests, and docs do use wasmtime::* -- and I'm sure that many embedders do that too -- but if we put wasmtime::error::Ok at wasmtime::Ok, then that glob import would mean that wasmtime::Ok replaces the prelude's use core::result::Result::Ok, which makes things like matching on results break.

having two paths to the same type means that it's inevitably going to be used both ways in different places. There are other files modified here which use crate::error::... instead of crate::... for example.

Having a top-level alias of an item defined in a nested module seems like a very minor blemish to me. Like I guess in a platonic ideal world it would be nice if it didn't exist, and there was only one path for the item, but it also doesn't seem like it actually hurts at all? Simultaneously, it seems pretty common for crates to re-export the most-common functionality from a nested module to the top level: even std does this with e.g. std::collections::HashMap and std::collections::hash_map::HashMap.

@alexcrichton
Copy link
Member

Personally I'm not too sold on the downstream churn argument. For example I'd disagree that anyhow::Foo wants to become wasmtime::error::Foo -- it will work, yes, but ergnomically it's probably not what you want. For the same reason as this PR, I'd rather read wasmtime::Foo than wasmtime::error::Foo (if possible).

I would also say that we're teeing up a lot of churn for downstream users because for embeddings it's likely that anyhow is used pervasively throughout rather than just for Wasmtime which means that conversion from wasmtime::Error to anyhow::Error will be required (the entire embedding probably won't want to change to wasmtime::Result). This'll require updating bindgen-generated traits, for example, to use the right error and any other wasm-y path which flows into Wasmtime. Worse yet all implementations of host functions which generate anyhow::Error won't work by-default and will require manual conversions to wasmtime::Error due to coherence. Basically I don't think "minimize churn" is a viable goal/end-state here, it's inevitably going to be a big, painful, change.

With this I'd say that the specific context of naming ErrorContext vs Context is more-or-less irrelevant. If anything it might make it nicer in case you need to have both anyhow's version and wasmtime's version in scope at the same time. (avoid as _ in the import)

I guess what I'm getting at is:

The best ergonomics is "you don't need to change anything in your existing code and you're already familiar with all the APIs"

Given two distinct nominal error types (anyhow::Error and wasmtime::Error) where you can't auto-convert one to the other (the anyhow::Error => wasmtime::Error direction) I don't think that this is achievable. Day-to-day usage can have similar ergonomics, but I really don't think that landing this change will be a simple search-and-replace-and-you're-done.


r.e. wasmtime::Ok -- well damn I'd agree that's probably not possible. Alas.


Having a top-level alias of an item defined in a nested module seems like a very minor blemish to me.

Agree yeah and I'm not saying it's absolutely imperative we don't have duplication. What I'm saying is that there should be a more-or-less canonical path that everything is used from. For example most crates use std::collections::HashMap and only if other stuff is also imported from the hash_map module might you import it from there. This PR as-is is a mish-mash of wasmtime::error::Thing vs wasmtime::Thing. It's inevitable this will exist to a certain degree, but what I'm asking for is a pass over this to canonicalize on wasmtime::Thing where possible.


Overall:

  • Due to wasmtime::*, I'd agree wasmtime::error is a required module.
  • I'd like to see a pass to rename crate::error::Thing at use-sites to crate::Thing in this PR.
  • Given the requirement of wasmtime::error seems fine to leave wasmtime::error::Context as-is.
  • I think it's worth setting expectations that we're doing what we can to smooth this transition but it will, in my opinion, almost surely be a pretty painful transition.

@fitzgen
Copy link
Member Author

fitzgen commented Jan 6, 2026

Overall:

  • Due to wasmtime::*, I'd agree wasmtime::error is a required module.

  • I'd like to see a pass to rename crate::error::Thing at use-sites to crate::Thing in this PR.

  • Given the requirement of wasmtime::error seems fine to leave wasmtime::error::Context as-is.

  • I think it's worth setting expectations that we're doing what we can to smooth this transition but it will, in my opinion, almost surely be a pretty painful transition.

I think we are mostly on the same page.

Regarding the last bullet point, I just don't want to give up on migration ergonomics by-default and only want us to do it deliberately when we have motivation that overrides those ergonomics. There's flex but we should be cognizant when we are making that trade off, not just accepting it as a lost cause from the start.

Latest commit has replaced all wasmtime::error::Thing uses with wasmtime::Thing other than the following two cases:

  • wasmtime::error::Ok, which doesn't have a top-level re-export as discussed earlier
  • in macro-generated code, we are doing UFCS to the wasmtime::error::Context::context function, and (as also discussed earlier) we don't have a top-level re-export of that function to use, but I also didn't want to switch away from UFCS

use crate::component::{
ComponentInstanceId, HasData, HasSelf, Instance, Resource, ResourceTable, ResourceTableError,
};
use crate::error::{Context as _, Result, anyhow, bail};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/::error// for non-Context things here

use crate::component::{
ComponentInstanceId, ComponentType, FutureReader, Lift, Lower, StreamReader,
};
use crate::error::{Context, Result, bail};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/::error// for non-Context things here

AsAccessor, ComponentInstanceId, ComponentType, FutureAny, Instance, Lift, Lower, StreamAny,
Val, WasmList,
};
use crate::error::{Context as _, Error, Result, anyhow, bail};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/::error// for non-Context things here

@@ -1,6 +1,6 @@
use super::{TypedResource, TypedResourceIndex};
use crate::error::{Result, bail};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/::error//

use crate::component::func::{LiftContext, LowerContext};
use crate::component::matching::InstanceType;
use crate::component::{ComponentType, Lift, Lower, Val};
use crate::error::{Result, anyhow, bail};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/::error//

@@ -1,9 +1,9 @@
use crate::error::{Result, anyhow};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/::error// (or maybe remove entirely due to the prelude import here)

@fitzgen fitzgen enabled auto-merge January 7, 2026 16:55
@fitzgen fitzgen added this pull request to the merge queue Jan 7, 2026
Merged via the queue into bytecodealliance:main with commit 96e1970 Jan 7, 2026
45 checks passed
@fitzgen fitzgen deleted the migrate-wasmtime-to-wasmtime-error branch January 7, 2026 17:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants