tinyhumansai/openhuman · error
[transport:manager] tunnel profile missing sessionToken or…
Error message
[transport:manager] tunnel profile missing sessionToken or pairingToken
What it means
raceLanAndTunnel() needs an auth token for the backend relay: sessionToken (reconnect path) or, failing that, pairingToken (first-connect path). Neither present means the profile cannot authenticate the socket.io tunnel:connect handshake at all. sessionToken ? 'session' : 'pairing' selects which field the relay checks.
Solutions
- Re-pair the device to obtain a fresh pairingToken (or a new sessionToken) — there is no way to refresh it from the client alone
- If you persisted the profile yourself, store sessionToken immediately after the first successful tunnel connect
- Treat this error in UI as 'device needs re-pairing', not as a network failure
Defensive patterns
Strategy: validation
Validate before calling
function hasTunnelCredentials(p: ConnectionProfile): boolean {
return p.kind !== 'tunnel' || Boolean(p.sessionToken || p.pairingToken);
} Try / catch
try { await manager.getTransport(); }
catch (err) {
if (err instanceof Error && err.message.includes('missing sessionToken or pairingToken')) {
await startRePairing(); // token is gone server-side; only re-pair can fix it
} else throw err;
} Prevention
- Persist sessionToken immediately after the first successful tunnel connect — pairing tokens are single-use
- Clear tunnel profiles on logout so a stale profile cannot be retried
- Surface this as 'device needs re-pairing' in UI
When it happens
Trigger: Session expired/rotated and the one-time pairing token was already consumed on an earlier connect (pairing tokens are single-use); logout cleared sessionToken without clearing the profile; pairing completed but tokens never persisted.
Common situations: Returning to a tunnel connection days later after the session lapsed; core revoked the device's session (devices domain) but the client still shows the profile; interrupted first-connect consumed the pairing token without delivering the session token.
Related errors
- [transport:manager] tunnel profile missing channelId or…
- [transport:local] HTTP
- [transport:manager] all transports failed to connect
- [transport:manager] cloud profile missing rpcUrl
- [transport:manager] lan profile missing rpcUrl
AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17).
Data as JSON: /api/errors/32c1f60dd95229ca.
Report an issue: GitHub.
Appendix: source
Thrown at app/src/services/transport/TransportManager.ts:119
throw new Error(`[transport:manager] unknown profile kind: ${kind}`);
}
/**
* Race LAN (with 2 s timeout) against Tunnel.
* Whichever responds to `openhuman.ping` first wins.
* If LAN wins but later fails, caller should call reset() to re-race.
*/
private async raceLanAndTunnel(): Promise<CoreTransport> {
const { rpcUrl, channelId, corePubkey, sessionToken, pairingToken, devicePrivkey } =
this.profile;
if (!channelId || !corePubkey) {
throw new Error('[transport:manager] tunnel profile missing channelId or corePubkey');
}
const tunnelToken = sessionToken ?? pairingToken;
if (!tunnelToken) {
throw new Error('[transport:manager] tunnel profile missing sessionToken or pairingToken');
}
const tunnelTransport = new TunnelTransport(
this.backendSocketUrl,
channelId,
corePubkey,
tunnelToken,
devicePrivkey,
sessionToken ? 'session' : 'pairing'
);
if (!rpcUrl) {
// No LAN URL — tunnel only.
log('[transport:manager] → TunnelTransport (no LAN URL)');
return tunnelTransport;
}
const lanTransport = new LanHttpTransport(rpcUrl, LAN_RACE_TIMEOUT_MS);View on GitHub (pinned to 7491200858)