tinyhumansai/openhuman · error · Error
[transport:manager] tunnel profile missing channelId or core
Error message
[transport:manager] tunnel profile missing channelId or corePubkey
What it means
A kind 'tunnel' profile must identify the relay channel (channelId) and the core's public key (corePubkey) so TunnelTransport can route and encrypt; missing either makes the tunnel unusable, so raceLanAndTunnel refuses before racing LAN against tunnel.
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 a221052e0d)
Solutions
- Re-run device pairing so both channelId and corePubkey are recorded
- Delete the half-paired device entry and pair again
- Add a load-time completeness assertion (see guard) that fails with the profile id
Example fix
// before
const tm = createTransportManager(profile, opts);
// after
if (profile.kind === 'tunnel' && (!profile.channelId || !profile.corePubkey)) {
throw new Error(`profile ${profile.id}: tunnel pairing incomplete — re-pair the device`);
}
const tm = createTransportManager(profile, opts); Defensive patterns
Strategy: validation
Validate before calling
function assertTunnelProfilePaired(p: ConnectionProfile): void {
if (p.kind === 'tunnel' && (!p.channelId || !p.corePubkey)) {
throw new Error(`profile ${p.id}: tunnel pairing incomplete (channelId/corePubkey missing) — re-pair`);
}
} Prevention
- Write channelId and corePubkey atomically — never persist a half-paired profile
- On interrupted pairing, delete the partial device entry before retrying
- Assert tunnel profile completeness at load time
When it happens
Trigger: getTransport() on a tunnel profile saved before pairing completed — the flow was interrupted after channel creation but before the core pubkey exchange, so one of the two fields is empty.
Common situations: Interrupted device pairing (security/devices domain); partial profile persistence from a crash mid-write; test fixtures missing tunnel fields.
Related errors
- [transport:manager] tunnel profile missing sessionToken or p
- [tunnel] no device keypair
- [transport:local] response missing result
- [transport:manager] cloud profile missing rpcUrl
- [transport:manager] lan profile missing rpcUrl
AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16).
Data as JSON: /api/errors/c5687cd7ed6d8821.
Report an issue: GitHub.