0xMiden / 0xMiden/web-sdk

A never-settling syncState wedges withSyncLock's coalescing forever — a fresh client still joins the corpse

Open
#321 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
1
Forks
21
Avg merge
12h 14m
Merged PRs (30d)
41

Description

## Symptom

One `syncState()` whose underlying RPC never settles kills sync **permanently for the whole realm**: every later `syncState()` — including from a freshly constructed client — parks instantly without issuing a single network request, and no client-side recovery can release it.

## Why

`withSyncLock` coalesces per `(dbId, methodId)` through a **module-level** `inFlight` map, and the entry is removed only in the promise's `finally`. A sync that never settles (on wasm32 the transport carries no deadline — the wasm `ApiClient` drops its `timeout_ms`) therefore stays in `inFlight` forever, and every subsequent caller joins the corpse's promise. Replacing the client doesn't help: the map (and the `miden-sync-` Web Lock the corpse holds) are shared module state, not client state.

## Evidence (live, on-device — from the 0xMiden/wallet#777 investigation)

- iOS simulator, one sync RPC forced to hang: the wallet evicted its lock holder and built a fresh client; the next tick's `syncState` produced **zero** network traffic and never settled.
- `navigator.locks.query()` at that moment: `held: ["miden-sync-default:exclusive"]`, `pending: []` — held by the abandoned call, and the new caller isn't even queued (it coalesced in `inFlight`).

## Expected

A single stuck call must not be able to wedge sync beyond its own lifetime. The root cure is the transport deadline (miden-client's wasm `ApiClient` ignoring `timeout_ms`); a defensive bound on how long an `inFlight` entry may be joined would additionally keep any future never-settling path from becoming realm-permanent.

## Impact

On mobile (wallet runs the client on the main thread, 3s idle sync) this is the unrecoverable half of wallet#777: after the wedge, the wallet is chain-blind until the app is killed.

Contributor guide

Open the contributing guide

Research direction

Look at the `withSyncLock` function and the module-level `inFlight` map. The bug is in the wasm `ApiClient` transport ignoring the `timeout_ms`. Start by examining the client construction and sync flow to understand where deadlines are set and enforced. The fix involves ensuring the transport respects timeouts and possibly adding a defensive bound to the `inFlight` coalescing. Testing requires simulating a hanging RPC in a wasm environment.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript, wasm
Domain
backend, mobile-dev, web-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.