paritytech / paritytech/host-rust-core

SSO remote-message decode failure reaches products as opaque `Unknown`, hiding a host/paired-device skew

Open
#826 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Swift
Stars
10
Forks
3
Avg merge
1d 10h
Merged PRs (30d)
148

Description

Summary

A product's resourceAllocation.request([AutoSigning]) fails consistently with:

requestResourceAllocation failed: Unknown: invalid SSO remote message: Could not decode `RemoteMessage::data`:

The decode failure is on the SSO leg between the desktop host and the paired signing device, not in the product and not a user decision. But at the product boundary it arrives as ResourceAllocationError::Unknown { reason } carrying a Rust-internal string, so a product cannot tell that its user's pairing is what needs attention — which is the one thing that would let it say something useful.

Environment

  • Polkadot Desktop 0.8.10 (@parity/truapi / @parity/truapi-host 0.16.0)
  • Product: jollity.paseo, built on @parity/product-sdk-host 0.20.0 → @parity/truapi 0.16.0 (same codec generation as the host — the product/host pair is in lockstep)
  • Paired signing device: Polkadot mobile app, version not established

Observed

2026-09-17T15:19:40.212Z [warn] [jollity.paseo] [permissions] statements allocation not granted
  HostCallFailedError: requestResourceAllocation failed: Unknown: invalid SSO remote message: Could not decode `RemoteMessage::data`:
2026-09-17T15:22:16.392Z [warn] ... same

Reproducible on every attempt. Every other host call from the same product in the same session succeeds: requestPermission for Remote{domains}, WebRtc and StatementSubmit all grant normally, and requestDevicePermission("Camera") works. Only the resource allocation fails.

Path

  1. runtime/capabilities/resources.rs:21ResourceAllocation::request checks for an active session, then calls confirm_user_action(ResourceAllocation). A refusal there has its own distinct reason ("User rejected resource allocation"), which we do not see — so the confirmation was given.
  2. It then builds a remote-authority context and waits on the paired signing host.
  3. host_logic/sso/messages.rs:491decode_remote_message fails: invalid SSO remote message: Could not decode `RemoteMessage::data` .
  4. That becomes SsoRemoteResponseError::Failure(String) and reaches the product as ResourceAllocationError::Unknown { reason }.

Two asks

1. Is a host ↔ paired-device version skew expected to fail this way?

@parity/truapi 0.15's wire-codec-2 changeset is explicit that "hosts and products must move together" because the handshake rides the envelope and the mismatch cannot be negotiated in band. That rule is enforced (and now visible) on the host↔product axis. Across the pairing there seems to be no equivalent guard: a device on a different generation pairs successfully and then fails at first use, with a decode error rather than anything naming the incompatibility. If that is the intended failure mode, it would help to say so in the docs; if not, refusing or warning at pair time would turn a mystery into a message.

2. Diagnosability at the product boundary.

SsoRemoteResponseError already distinguishes Cancelled, LocalDisconnected, PeerDisconnected and Failure, but all four collapse into Unknown { reason: String } by the time a product sees them. A product therefore cannot distinguish:

  • the paired device is incompatible
  • the paired device is disconnected
  • the user cancelled on the device
  • something genuinely unknown

…and so cannot tell the user the one thing that would fix it ("open the Polkadot app on your phone", "update it", "re-pair"). A typed variant — e.g. RemoteAuthorityUnavailable / RemoteAuthorityIncompatible — would be enough; products can keep treating Unknown as opaque.

Why this matters downstream

Our app pre-asks for the AutoSigning allowance in a one-time permission gate, so the failure lands on a row the user is looking at, with a retry button that can never succeed. Until we added error classification of our own, that row read "Denied" — i.e. the product was telling the user they had refused something they were never asked about. Any product that maps an allocation failure to "the user said no" will do the same, and the API as it stands gives it no way to know better.

Happy to test a fix or supply more logs — the full host log for the session is available.

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 runtime/capabilities/resources.rs:21 and host_logic/sso/messages.rs:491, then trace SsoRemoteResponseError into ResourceAllocationError::Unknown. Check the existing Cancelled, LocalDisconnected, PeerDisconnected, and Failure cases and the host/device version-skew behavior. Done means the product boundary preserves actionable distinctions, with the expected pairing behavior documented or guarded.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
api, backend-api-design
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.