{"record":{"id":"26e002aed9b52e11","repo":"stablyai/orca","slug":"relay-credential-install-result-does-not-match-pai","errorCode":null,"errorMessage":"relay credential install result does not match pairing journal","messagePattern":"relay credential install result does not match pairing journal","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"mobile/src/transport/mobile-relay-credential-bundle.ts","lineNumber":59,"sourceCode":"  })\n  .strict()\n\nexport type MobileRelayCredentialBundle = z.infer<typeof MobileRelayCredentialBundleSchema>\n\nfunction credentialKey(hostId: string): string {\n  return `orca.mobile-relay.credentials.${hostId}`\n}\n\nexport function promotePairingJournalCredential(args: {\n  journal: MobileRelayPairingJournal\n  installed: DeviceCredentialInstalled\n}): MobileRelayCredentialBundle {\n  const { journal, installed } = args\n  if (\n    installed.reqId !== journal.metadata.installReqId ||\n    installed.authorizationMode !== journal.metadata.authorizationMode\n  ) {\n    throw new Error('relay credential install result does not match pairing journal')\n  }\n  return MobileRelayCredentialBundleSchema.parse({\n    v: 1,\n    hostId: journal.metadata.host.id,\n    deviceToken: journal.secrets.deviceToken,\n    current: {\n      token: journal.secrets.pendingResumeToken,\n      hash: journal.metadata.pendingResumeTokenHash,\n      version: installed.currentVersion,\n      expiresAt: installed.resumeExpiresAt\n    }\n  })\n}\n\nexport async function readMobileRelayCredentialBundle(\n  hostId: string\n): Promise<MobileRelayCredentialBundle | null> {\n  requireNativeSecretStore()","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/mobile/src/transport/mobile-relay-credential-bundle.ts#L41-L77","documentation":"Thrown by `promotePairingJournalCredential` when the install RPC result's `reqId` or `authorizationMode` does not match what the pairing journal recorded in its metadata. The journal is the durable record of which install request was initiated; the install result must echo the same `installReqId` and `authorizationMode` or the promotion is unsafe (it could install a credential from a different authorization flow).","triggerScenarios":"Passing an `installed` result from a different pairing attempt than the journal refers to; concurrent pairing flows racing on the same host; journal corruption where `metadata.installReqId` is stale; a server that echoes a different `authorizationMode` than requested.","commonSituations":"Two pairing attempts running in parallel (e.g. user retried while the first was in flight); a journal that was not cleared after a failed attempt; server-side bug returning the wrong mode.","solutions":["Ensure only one pairing flow is active per host at a time — clear the journal before starting fresh.","Verify the `installReqId` you pass matches `journal.metadata.installReqId` before calling promote.","If the journal is stale, discard it and re-run pairing from the start."],"exampleFix":"// before\npromotePairingJournalCredential({ journal: oldJournal, installed: freshInstall })\n// -> install result does not match pairing journal\n\n// after\nif (installed.reqId !== journal.metadata.installReqId ||\n    installed.authorizationMode !== journal.metadata.authorizationMode) {\n  await discardPairingJournal(hostId)\n  throw new Error('journal/install mismatch — restart pairing')\n}\nreturn promotePairingJournalCredential({ journal, installed })","handlingStrategy":"validation","validationCode":"function installMatchesJournal(journal: MobileRelayPairingJournal, installed: DeviceCredentialInstalled): boolean {\n  return installed.reqId === journal.metadata.installReqId &&\n         installed.authorizationMode === journal.metadata.authorizationMode\n}\nif (!installMatchesJournal(journal, installed)) { await discardJournal(); throw new Error('mismatch') }","typeGuard":"function isJournalMatch(j: MobileRelayPairingJournal, i: DeviceCredentialInstalled): boolean {\n  return i.reqId === j.metadata.installReqId && i.authorizationMode === j.metadata.authorizationMode\n}","tryCatchPattern":"try { promotePairingJournalCredential({ journal, installed }) } catch (e) { if (e.message === 'relay credential install result does not match pairing journal') { await clearPairingJournal(hostId); rethrowAsRepairable(e) } else throw e }","preventionTips":["Serialize pairing flows per host — never run two in parallel.","Clear the journal before starting a fresh pairing attempt.","Cross-check installReqId against the journal before promote."],"tags":["relay","credentials","pairing","consistency"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}