stablyai/orca · error · RelayOuterError
relay_outer_${code}
Error message
relay_outer_${code} What it means
RelayOuterError is thrown (message relay_outer_${code}) when the cell hello has ok:false with a code in [4000,4999] during the pairing dial. The cell rejected the pairing credential supplied in the relay-auth frame.
Source
Thrown at mobile/src/transport/mobile-relay-physical-client.ts:132
socket.onerror = () => fail(new Error('relay transport error'))
socket.onclose = (event) => fail(new RelayOuterError(event.code || 1006))
function acceptRelayHello(raw: unknown): void {
if (typeof raw !== 'string') {
throw new Error('expected plaintext relay hello')
}
let value: unknown
try {
value = JSON.parse(raw)
} catch {
throw new Error('invalid relay hello JSON')
}
const parsed = RelayPhoneHelloSchema.safeParse(value)
if (!parsed.success) {
throw new Error('invalid relay hello')
}
if (!parsed.data.ok) {
throw new RelayOuterError(parsed.data.code)
}
if (parsed.data.credentialKind !== (args.expectedCredentialKind ?? 'invite')) {
throw new Error('relay credential resolved as an unexpected credential kind')
}
outerReady = true
log('info', 'Relay: cell accepted credential', 'Starting E2EE handshake')
channel.start()
}
function fail(error: Error): void {
if (closed) {
return
}
closed = true
if (intentionallyClosed) {
log('info', 'Relay: pairing socket closed', cellHost)
} else {
log('warn', 'Relay: pairing socket closed', pairingRelayErrorDetail(error))View on GitHub (pinned to 1136503c6a)
Solutions
- Decode the 4xxx code per the relay protocol and map it to user guidance.
- Refresh the invite from the desktop host for expired/used invites.
- For resume failures, fall back to a fresh pair.
- Check leaseExpiresAt / resumeExpiresAt to catch clock skew.
Defensive patterns
Strategy: try-catch
Type guard
import { RelayOuterError } from './mobile-relay-e2ee-link'
function isRelayOuterError(error: unknown): error is RelayOuterError {
return error instanceof RelayOuterError
} Try / catch
import { RelayOuterError } from './mobile-relay-e2ee-link'
try {
const client = connectMobileRelayForPairing(args)
} catch (error) {
if (error instanceof RelayOuterError) {
// map error.code to UX: refresh invite, re-pair, or report revoked
}
} Prevention
- Map every 4xxx RelayOuterError code to a concrete user action.
- Check lease/refresh timestamps locally before dialing to pre-empt expiry.
- Do not replay a credential after a 4xxx rejection.
When it happens
Trigger: Expired or already-used invite, unknown/revoked resume token, or a credential whose version was superseded during the pairing dial.
Common situations: Invite expired before pairing completed; resume token stale after host rotation; replaying a consumed invite; clock skew making a lease look expired.
Related errors
- relay_outer_${code}
- expected plaintext relay hello
- invalid relay hello JSON
- invalid relay hello
- relay credential resolved as an unexpected credential kind
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/e4602678ddeb370f.
Report an issue: GitHub.