{"record":{"id":"cd7422c003449e06","repo":"tinyhumansai/openhuman","slug":"transport-manager-cloud-profile-missing-rpcurl","errorCode":null,"errorMessage":"[transport:manager] cloud profile missing rpcUrl","messagePattern":"\\[transport:manager\\] cloud profile missing rpcUrl","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"app/src/services/transport/TransportManager.ts","lineNumber":80,"sourceCode":"    }\n  }\n\n  // -- selection logic -------------------------------------------------------\n\n  private async selectTransport(): Promise<CoreTransport> {\n    const { kind } = this.profile;\n    log('[transport:manager] selecting kind=%s id=%s', kind, this.profile.id);\n\n    if (kind === 'local') {\n      const t = new LocalTransport(this.localRpcUrl, this.localToken);\n      log('[transport:manager] → LocalTransport');\n      return t;\n    }\n\n    if (kind === 'cloud') {\n      const { rpcUrl, sessionToken } = this.profile;\n      if (!rpcUrl) {\n        throw new Error('[transport:manager] cloud profile missing rpcUrl');\n      }\n      const t = new CloudHttpTransport(rpcUrl, sessionToken ?? null);\n      log('[transport:manager] → CloudHttpTransport rpcUrl=%s', rpcUrl);\n      return t;\n    }\n\n    if (kind === 'lan') {\n      const { rpcUrl } = this.profile;\n      if (!rpcUrl) {\n        throw new Error('[transport:manager] lan profile missing rpcUrl');\n      }\n      const t = new LanHttpTransport(rpcUrl);\n      log('[transport:manager] → LanHttpTransport rpcUrl=%s', rpcUrl);\n      return t;\n    }\n\n    if (kind === 'tunnel') {\n      return this.raceLanAndTunnel();","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/a221052e0df5b1f7598fceba7329fd1af95d6699/app/src/services/transport/TransportManager.ts#L62-L98","documentation":"TransportManager.buildTransport requires profile.rpcUrl for kind 'cloud'; the selected ConnectionProfile has kind 'cloud' but an empty/undefined rpcUrl, so a CloudHttpTransport cannot even be constructed. It is a profile-data error, not a network error — nothing was dialed yet.","triggerScenarios":"manager.getTransport() with a profile like { kind: 'cloud', rpcUrl: undefined, sessionToken } — a persisted profile saved before the field existed, one built from empty backend-URL config, or a hand-built test profile.","commonSituations":"Old persisted profile schema missing the cloud URL; migration that dropped the field; tests constructing profiles inline; backend URL env var unset when the profile was created.","solutions":["Populate rpcUrl (the cloud backend RPC endpoint) on the profile before creating the manager","If the profile comes from persisted state, re-run the connection save/pairing flow so the current schema fills it","Add a load-time completeness assertion naming the profile id so the failure is actionable","Delete the broken profile entry and recreate it via the UI flow"],"exampleFix":"// before\nconst tm = createTransportManager(profile, opts);\n\n// after\nif (profile.kind === 'cloud' && !profile.rpcUrl) {\n  throw new Error(`profile ${profile.id}: cloud rpcUrl missing — re-pair this connection`);\n}\nconst tm = createTransportManager(profile, opts);","handlingStrategy":"validation","validationCode":"function assertProfileComplete(p: ConnectionProfile): void {\n  if ((p.kind === 'cloud' || p.kind === 'lan') && !p.rpcUrl) {\n    throw new Error(`profile ${p.id} (${p.kind}) is missing rpcUrl — re-pair the connection`);\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate ConnectionProfile at load time, before any TransportManager is built","Create profiles only through the pairing/connection UI flow, never by hand-editing persisted JSON","Fail with the profile id in the message so the broken entry is identifiable"],"tags":["transport","cloud","connection-profile","config"],"backgroundTag":null,"analyzedSha":"a221052e0df5b1f7598fceba7329fd1af95d6699","analyzedAt":"2026-08-16T12:47:06.542Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}