stablyai/orca · error · Error

relay endpoint reconciliation became unavailable

Error message

relay endpoint reconciliation became unavailable

What it means

Thrown in `upgradeDirectMobileRelay` when the reconciliation `getEndpoints` call (after a successful `provisionRelay`) returns `'method-not-found'`. The desktop supported `getEndpoints` at the start of the flow but stopped supporting it mid-upgrade — indicating the desktop went away, downgraded, or restarted under an older protocol version.

Source

Thrown at mobile/src/transport/mobile-relay-direct-upgrade.ts:90

    return publishCommitted(args.host, journal, initial, dependencies)
  }
  if (!initial.relay) {
    throw new Error('relay endpoint unavailable for direct pairing upgrade')
  }

  const provisionResponse = await args.client.sendRequest('pairing.provisionRelay', {
    reqId: journal.reqId,
    newResumeTokenHash: journal.pendingResumeTokenHash
  })
  if (isMethodNotFound(provisionResponse)) {
    await dependencies.clearJournal(args.host.id)
    return null
  }
  const installed = DeviceCredentialInstalledSchema.parse(requireSuccess(provisionResponse))
  assertDirectInstall(journal, installed)
  const reconciled = await getEndpoints(args.client, journal.reqId)
  if (reconciled === 'method-not-found') {
    throw new Error('relay endpoint reconciliation became unavailable')
  }
  assertCommitted(reconciled, installed)
  return publishCommitted(args.host, journal, reconciled, dependencies)
}

async function publishCommitted(
  host: HostProfile,
  journal: MobileRelayDirectUpgradeJournal,
  endpoints: PairingGetEndpointsResult,
  dependencies: Dependencies
): Promise<MobileRelayDirectUpgradeResult> {
  if (endpoints.installStatus?.state !== 'committed' || !endpoints.relay) {
    throw new Error('direct pairing upgrade was not authoritatively committed')
  }
  const installed = endpoints.installStatus.result
  assertDirectInstall(journal, installed)
  const bundle = MobileRelayCredentialBundleSchema.parse({
    v: 1,

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Abort the upgrade and clear the journal only if safe; otherwise preserve it for resume.
  2. Re-establish the RPC client and retry the upgrade from the top — the journal's stable `reqId` makes this idempotent.
  3. Verify desktop protocol version before retrying.

Example fix

// before
// bubbles up; journal left in limbo

// after
try { return await upgradeDirectMobileRelay({ client, host }) }
catch (e) {
  if (e.message === 'relay endpoint reconciliation became unavailable') {
    await reconnectClient()
    return await upgradeDirectMobileRelay({ client: freshClient, host })
  }
  throw e
}
Defensive patterns

Strategy: retry

Validate before calling

// Validate the RPC client is still on a capable desktop before retry:
await assertEndpointMethodSupported(client, 'pairing.getEndpoints')

Try / catch

try { return await upgradeDirectMobileRelay({ client, host }) } catch (e) { if (e.message === 'relay endpoint reconciliation became unavailable') { await reconnectClient(); return await upgradeDirectMobileRelay({ client: freshClient, host }) } throw e }

Prevention

When it happens

Trigger: Desktop disconnected or restarted between `provisionRelay` and the second `getEndpoints`; the RPC connection was migrated to a different desktop instance running an older version; method was removed server-side during the flow.

Common situations: User quit/restarted the desktop mid-upgrade; desktop auto-update rolled back during the operation; load balancer routed the second call to an older desktop.

Related errors


AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12). Data as JSON: /api/errors/59fe3624c2000b29. Report an issue: GitHub.