paritytech / paritytech/triangle-js-sdks

Several bugs in host-container and host-api surfaced while porting

Open
#138 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
3
Forks
1
Avg merge
1d 14h
Merged PRs (30d)
8

Description

While porting pieces of triangle-js-sdks into a downstream codebase we uncovered a number of bugs in the host-container / host-api sources. The same patterns still appear on main at the time of writing. Filing here for tracking — happy to open follow-up PRs if useful.

1. handleSubscription leaks the handler's cleanup when interrupt() is called asynchronously

File: packages/host-api/src/transport.ts (around L351–367, the handleSubscription start handler).

The interrupt callback passed to the handler does interrupted = true; subscriptions.delete(requestId) and posts an interrupt message, but the handler's returned cleanup function is only invoked on the synchronous-interrupt branch (if (interrupted) { unsubscribe(); }). If the handler stashes interrupt and calls it asynchronously (e.g. from a setInterval tick), the stored unsubscribe is removed from the map without ever being called — intervals, listeners, sockets etc. leak.

2. chainHead_v1_follow rejection is silently swallowed

File: packages/host-container/src/chainConnectionManager.ts (around L534–537, startFollow's pending-request reject).

The reject handler only clears pendingRequestId and removes the follow from followSubscriptions. Nothing propagates the failure back to the subscriber. If the node rejects the RPC (method unsupported, connection failure, etc.) the product-side subscription stays "alive" from the transport's perspective but never receives events and never sees an interrupt — it just hangs forever.

3. followSubscriptionId on chain-op requests is ignored; host arbitrarily picks one follow per chain

File: packages/host-container/src/createContainer.ts (L708–716 for remote_chain_head_header and the same pattern across _body, _storage, _call, _unpin, _continue, _stop_operation).

Each handler discards followSubscriptionId from the incoming request and calls manager.getChainFollowSubId(genesisHash), which returns the first follow found on that chain (chainConnectionManager.ts L584–587). With multiple concurrent follows on the same chain (e.g. one with runtime, one without — both legal), every chain-op routes to an arbitrary one and silently uses the wrong pin set.

4. JSON-RPC error code/message are discarded on chain-op failures

File: packages/host-container/src/createContainer.ts (every chain-op catch — e.g. L719, L741, L773, L800, L822, L844, L866).

Each catch does new GenericError({ reason: String(e) }), while sendRequest in chainConnectionManager.ts (L473) rejects with the raw JSON-RPC parsed.error object ({code, message, data?}). String({...}) is '[object Object]' — so the node's actual error code and message never reach the product, which then has to hardcode -32603 when forwarding to the JSON-RPC caller.


Happy to provide more detail or split into separate issues — let me know which is more useful for tracking.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the cited handlers in packages/host-api/src/transport.ts, packages/host-container/src/chainConnectionManager.ts, and packages/host-container/src/createContainer.ts. Trace interruption, follow rejection, followSubscriptionId routing, and sendRequest error handling. Done means asynchronous cleanup runs, follow failures reach subscribers, chain operations use the requested follow, and JSON-RPC code and message are preserved.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.