Summary
The wasm SDK is intended for browser use, but state-transition wait operations crash in browser/wasm32-unknown-unknown when waitTimeoutMs is provided.
This is not just a timeout error being returned to the caller. The SDK enters a Rust timeout path that is not safe in this target and panics instead.
Why this matters
In browser integrations, callers reasonably expect waitTimeoutMs to either:
- enforce a timeout and return a normal SDK error, or
- be rejected as unsupported on this target
Instead, using the timeout setting can crash the wasm execution path.
Root cause
waitTimeoutMs is exposed in the wasm-facing PutSettings type and converted into Rust PutSettings.wait_timeout:
That timeout is then consumed by the state-transition wait path here:
Specifically:
tokio::time::timeout(timeout, future)
In browser wasm, that path crashes instead of producing a normal timeout result.
Not the trusted-context prefetch path
The initial suspicion was that trusted mode or trusted-context prefetch was the browser regression. That does not appear to be the direct cause.
Trusted mode in the JS SDK only prefetches the trusted context during connect:
The wasm trusted context provider itself also avoids the explicit reqwest .timeout(...) configuration on wasm and only applies that 30s timeout on non-wasm targets:
So the browser crash appears to come from the state-transition wait timeout path, not from trusted-context prefetch itself.
JS call path
The JS Evo SDK forwards state-transition waits directly into wasm:
That means browser callers can hit this just by passing waitTimeoutMs through normal SDK usage.
Expected behavior
One of these should happen instead:
waitTimeoutMs works in browser wasm and returns a normal timeout error.
waitTimeoutMs is explicitly unsupported on wasm32-unknown-unknown, and the SDK rejects it early with a clear error.
- The wasm JS wrapper handles timeout containment outside Rust and does not let the wasm runtime panic.
Suggested fix direction
SDK-side fix is preferable, because the current API advertises browser-usable timeout settings.
Reasonable options:
- gate the Rust timeout path on
target_arch = "wasm32" and use a wasm-safe timer strategy there
- or reject
waitTimeoutMs during wasm settings parsing / state-transition wait setup with a clear unsupported-on-wasm error
An app-side Promise.race watchdog can mitigate this externally, but that is only a workaround and does not fix the SDK contract.
Repro shape
Any browser flow that calls wasm state-transition wait/broadcast-and-wait with waitTimeoutMs set is affected, for example:
await sdk.stateTransitions.broadcastAndWait(stateTransition, {
waitTimeoutMs: 30000,
});
Affected area
packages/wasm-sdk
packages/rs-sdk
- browser/wasm consumers of
js-evo-sdk
Summary
The wasm SDK is intended for browser use, but state-transition wait operations crash in browser/
wasm32-unknown-unknownwhenwaitTimeoutMsis provided.This is not just a timeout error being returned to the caller. The SDK enters a Rust timeout path that is not safe in this target and panics instead.
Why this matters
In browser integrations, callers reasonably expect
waitTimeoutMsto either:Instead, using the timeout setting can crash the wasm execution path.
Root cause
waitTimeoutMsis exposed in the wasm-facingPutSettingstype and converted into RustPutSettings.wait_timeout:packages/wasm-sdk/src/settings.rs#L137-L141packages/wasm-sdk/src/settings.rs#L192-L230That timeout is then consumed by the state-transition wait path here:
packages/rs-sdk/src/platform/transition/broadcast.rs#L232-L259Specifically:
In browser wasm, that path crashes instead of producing a normal timeout result.
Not the trusted-context prefetch path
The initial suspicion was that trusted mode or trusted-context prefetch was the browser regression. That does not appear to be the direct cause.
Trusted mode in the JS SDK only prefetches the trusted context during connect:
packages/js-evo-sdk/src/sdk.ts#L98-L129The wasm trusted context provider itself also avoids the explicit reqwest
.timeout(...)configuration on wasm and only applies that 30s timeout on non-wasm targets:packages/rs-sdk-trusted-context-provider/src/provider.rs#L145-L146packages/rs-sdk-trusted-context-provider/src/provider.rs#L148-L160So the browser crash appears to come from the state-transition wait timeout path, not from trusted-context prefetch itself.
JS call path
The JS Evo SDK forwards state-transition waits directly into wasm:
packages/js-evo-sdk/src/state-transitions/facade.ts#L19-L32That means browser callers can hit this just by passing
waitTimeoutMsthrough normal SDK usage.Expected behavior
One of these should happen instead:
waitTimeoutMsworks in browser wasm and returns a normal timeout error.waitTimeoutMsis explicitly unsupported onwasm32-unknown-unknown, and the SDK rejects it early with a clear error.Suggested fix direction
SDK-side fix is preferable, because the current API advertises browser-usable timeout settings.
Reasonable options:
target_arch = "wasm32"and use a wasm-safe timer strategy therewaitTimeoutMsduring wasm settings parsing / state-transition wait setup with a clear unsupported-on-wasm errorAn app-side
Promise.racewatchdog can mitigate this externally, but that is only a workaround and does not fix the SDK contract.Repro shape
Any browser flow that calls wasm state-transition wait/broadcast-and-wait with
waitTimeoutMsset is affected, for example:Affected area
packages/wasm-sdkpackages/rs-sdkjs-evo-sdk