stablyai/orca · error · Error

relay credential install result does not match pairing journ

Error message

relay credential install result does not match pairing journal

What it means

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).

Source

Thrown at mobile/src/transport/mobile-relay-credential-bundle.ts:59

  })
  .strict()

export type MobileRelayCredentialBundle = z.infer<typeof MobileRelayCredentialBundleSchema>

function credentialKey(hostId: string): string {
  return `orca.mobile-relay.credentials.${hostId}`
}

export function promotePairingJournalCredential(args: {
  journal: MobileRelayPairingJournal
  installed: DeviceCredentialInstalled
}): MobileRelayCredentialBundle {
  const { journal, installed } = args
  if (
    installed.reqId !== journal.metadata.installReqId ||
    installed.authorizationMode !== journal.metadata.authorizationMode
  ) {
    throw new Error('relay credential install result does not match pairing journal')
  }
  return MobileRelayCredentialBundleSchema.parse({
    v: 1,
    hostId: journal.metadata.host.id,
    deviceToken: journal.secrets.deviceToken,
    current: {
      token: journal.secrets.pendingResumeToken,
      hash: journal.metadata.pendingResumeTokenHash,
      version: installed.currentVersion,
      expiresAt: installed.resumeExpiresAt
    }
  })
}

export async function readMobileRelayCredentialBundle(
  hostId: string
): Promise<MobileRelayCredentialBundle | null> {
  requireNativeSecretStore()

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Ensure only one pairing flow is active per host at a time — clear the journal before starting fresh.
  2. Verify the `installReqId` you pass matches `journal.metadata.installReqId` before calling promote.
  3. If the journal is stale, discard it and re-run pairing from the start.

Example fix

// before
promotePairingJournalCredential({ journal: oldJournal, installed: freshInstall })
// -> install result does not match pairing journal

// after
if (installed.reqId !== journal.metadata.installReqId ||
    installed.authorizationMode !== journal.metadata.authorizationMode) {
  await discardPairingJournal(hostId)
  throw new Error('journal/install mismatch — restart pairing')
}
return promotePairingJournalCredential({ journal, installed })
Defensive patterns

Strategy: validation

Validate before calling

function installMatchesJournal(journal: MobileRelayPairingJournal, installed: DeviceCredentialInstalled): boolean {
  return installed.reqId === journal.metadata.installReqId &&
         installed.authorizationMode === journal.metadata.authorizationMode
}
if (!installMatchesJournal(journal, installed)) { await discardJournal(); throw new Error('mismatch') }

Type guard

function isJournalMatch(j: MobileRelayPairingJournal, i: DeviceCredentialInstalled): boolean {
  return i.reqId === j.metadata.installReqId && i.authorizationMode === j.metadata.authorizationMode
}

Try / catch

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 }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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