Skip to content

bug(wasm-sdk): using waitTimeoutMs in the browser crashes wasm state-transition waits #3499

@PastaPastaPasta

Description

@PastaPastaPasta

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:

  1. waitTimeoutMs works in browser wasm and returns a normal timeout error.
  2. waitTimeoutMs is explicitly unsupported on wasm32-unknown-unknown, and the SDK rejects it early with a clear error.
  3. 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

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