{"record":{"id":"59fe3624c2000b29","repo":"stablyai/orca","slug":"relay-endpoint-reconciliation-became-unavailable","errorCode":null,"errorMessage":"relay endpoint reconciliation became unavailable","messagePattern":"relay endpoint reconciliation became unavailable","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"mobile/src/transport/mobile-relay-direct-upgrade.ts","lineNumber":90,"sourceCode":"    return publishCommitted(args.host, journal, initial, dependencies)\n  }\n  if (!initial.relay) {\n    throw new Error('relay endpoint unavailable for direct pairing upgrade')\n  }\n\n  const provisionResponse = await args.client.sendRequest('pairing.provisionRelay', {\n    reqId: journal.reqId,\n    newResumeTokenHash: journal.pendingResumeTokenHash\n  })\n  if (isMethodNotFound(provisionResponse)) {\n    await dependencies.clearJournal(args.host.id)\n    return null\n  }\n  const installed = DeviceCredentialInstalledSchema.parse(requireSuccess(provisionResponse))\n  assertDirectInstall(journal, installed)\n  const reconciled = await getEndpoints(args.client, journal.reqId)\n  if (reconciled === 'method-not-found') {\n    throw new Error('relay endpoint reconciliation became unavailable')\n  }\n  assertCommitted(reconciled, installed)\n  return publishCommitted(args.host, journal, reconciled, dependencies)\n}\n\nasync function publishCommitted(\n  host: HostProfile,\n  journal: MobileRelayDirectUpgradeJournal,\n  endpoints: PairingGetEndpointsResult,\n  dependencies: Dependencies\n): Promise<MobileRelayDirectUpgradeResult> {\n  if (endpoints.installStatus?.state !== 'committed' || !endpoints.relay) {\n    throw new Error('direct pairing upgrade was not authoritatively committed')\n  }\n  const installed = endpoints.installStatus.result\n  assertDirectInstall(journal, installed)\n  const bundle = MobileRelayCredentialBundleSchema.parse({\n    v: 1,","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/mobile/src/transport/mobile-relay-direct-upgrade.ts#L72-L108","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Abort the upgrade and clear the journal only if safe; otherwise preserve it for resume.","Re-establish the RPC client and retry the upgrade from the top — the journal's stable `reqId` makes this idempotent.","Verify desktop protocol version before retrying."],"exampleFix":"// before\n// bubbles up; journal left in limbo\n\n// after\ntry { return await upgradeDirectMobileRelay({ client, host }) }\ncatch (e) {\n  if (e.message === 'relay endpoint reconciliation became unavailable') {\n    await reconnectClient()\n    return await upgradeDirectMobileRelay({ client: freshClient, host })\n  }\n  throw e\n}","handlingStrategy":"retry","validationCode":"// Validate the RPC client is still on a capable desktop before retry:\nawait assertEndpointMethodSupported(client, 'pairing.getEndpoints')","typeGuard":null,"tryCatchPattern":"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 }","preventionTips":["The stable journal reqId makes retry idempotent — reuse it after reconnect.","Verify desktop protocol version after reconnect before retrying.","Abort and preserve the journal if the desktop is persistently older."],"tags":["relay","upgrade","protocol-version","consistency"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}