tinyhumansai/openhuman · error
[transport:manager] tunnel profile missing channelId or…
Error message
[transport:manager] tunnel profile missing channelId or corePubkey
What it means
For kind === 'tunnel' the manager's raceLanAndTunnel() destructures channelId and corePubkey from the profile and refuses to proceed without both — they are the minimum to address the desktop core through the backend relay (channelId names the tunnel; corePubkey seals the first handshake frame). Without them the E2E-encrypted XChaCha20-Poly1305 path cannot even start.
Solutions
- Re-pair the device through the devices/pairing flow so channelId and corePubkey are freshly issued and persisted
- Validate the tunnel profile fields before createTransportManager and route the user to re-pairing UI when missing
- If the core workspace was reset, delete the stale profile on the client first so pairing starts clean
Defensive patterns
Strategy: validation
Validate before calling
function assertTunnelProfileReady(p: ConnectionProfile): void {
if (p.kind === 'tunnel' && (!p.channelId || !p.corePubkey)) {
throw new Error('tunnel profile incomplete — re-pair the device to obtain channelId and corePubkey');
}
} Type guard
function isPairableTunnelProfile(p: ConnectionProfile): boolean {
return p.kind !== 'tunnel' || (typeof p.channelId === 'string' && typeof p.corePubkey === 'string' && p.channelId.length > 0 && p.corePubkey.length > 0);
} Prevention
- Persist channelId + corePubkey together at pairing completion, not incrementally
- If the core workspace is reset, clear tunnel profiles on the client in the same operation
- Route users to the pairing UI when either field is missing instead of attempting connect
When it happens
Trigger: Device pairing completed only partially (channel allocated but core pubkey never recorded); persisted tunnel profile trimmed by a migration; pairing record for this device deleted on the core side (src/openhuman/security/devices/) while the client kept the profile.
Common situations: Pairing flow interrupted (app closed during pair); core workspace reset wiping devices.db while the phone/iOS client kept its tunnel profile; schema change renaming fields.
Related errors
- [transport:manager] tunnel profile missing sessionToken or…
- [transport:manager] all transports failed to connect
- [transport:manager] cloud profile missing rpcUrl
- [transport:manager] lan profile missing rpcUrl
- [transport:manager] unknown profile kind
AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17).
Data as JSON: /api/errors/c5687cd7ed6d8821.
Report an issue: GitHub.
Appendix: source
Thrown at app/src/services/transport/TransportManager.ts:114
if (kind === 'tunnel') {
return this.raceLanAndTunnel();
}
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.View on GitHub (pinned to 7491200858)