{"record":{"id":"90a754535ea5255d","repo":"tinyhumansai/openhuman","slug":"transport-cloud-response-missing-result","errorCode":null,"errorMessage":"[transport:cloud] response missing result","messagePattern":"\\[transport:cloud\\] response missing result","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/src/services/transport/CloudHttpTransport.ts","lineNumber":85,"sourceCode":"      }\n      throw err;\n    } finally {\n      clearTimeout(timeoutId);\n    }\n\n    if (!response.ok) {\n      const text = await response.text();\n      throw new Error(`[transport:cloud] HTTP ${response.status}: ${text || response.statusText}`);\n    }\n\n    const json = (await response.json()) as JsonRpcResponse<T>;\n\n    if (json.error) {\n      logErr('[transport:cloud] ← %s error: %s', method, json.error.message);\n      throw new Error(json.error.message ?? 'Cloud RPC returned an error');\n    }\n    if (!Object.prototype.hasOwnProperty.call(json, 'result')) {\n      throw new Error('[transport:cloud] response missing result');\n    }\n\n    log('[transport:cloud] ← %s id=%d ok', method, id);\n    return json.result as T;\n  }\n\n  async *stream<T>(\n    method: string,\n    params: unknown,\n    opts?: { signal?: AbortSignal }\n  ): AsyncIterable<T> {\n    const result = await this.call<T>(method, params, opts);\n    yield result;\n  }\n\n  async isHealthy(): Promise<boolean> {\n    try {\n      await this.call('openhuman.ping', {}, { signal: AbortSignal.timeout(5000) });","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/749120085864ce16e0f273c7b86fac7740b39c5b/app/src/services/transport/CloudHttpTransport.ts#L67-L103","documentation":"The cloud core's 2xx response parsed as JSON but the envelope has neither error nor an own 'result' property — a JSON-RPC 2.0 protocol violation from the remote side. Checked with hasOwnProperty, so {result: null} is fine; only a structurally absent result key throws.","triggerScenarios":"A cloud gateway answering 200 with its own envelope ({success, data}) instead of forwarding the JSON-RPC frame; a service worker or CDN rewriting the body; a cloud core bug serializing notifications instead of responses.","commonSituations":"rpcUrl pointing at an API gateway route that wraps responses; middleware (auth edge, WAF) substituting a JSON status body; mismatched API versions between transport and cloud core.","solutions":["curl the exact rpcUrl with a JSON-RPC frame and inspect the raw envelope returned","Point the profile at the core's true /rpc endpoint, not a wrapping API route","Disable/adjust any service worker or edge middleware that rewrites POST /rpc bodies","If the cloud core itself is malformed, capture json.error and file it with the response id for server-side correlation"],"exampleFix":"// before\nconst t = new CloudHttpTransport('https://cloud.example.com/api', token);\n\n// after\nconst t = new CloudHttpTransport('https://cloud.example.com/rpc', token);","handlingStrategy":"type-guard","validationCode":"async function servesJsonRpc(url: string, token: string | null): Promise<boolean> {\n  const r = await fetch(url, {\n    method: 'POST',\n    headers: { 'Content-Type': 'application/json', ...(token ? { Authorization: `Bearer ${token}` } : {}) },\n    body: JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'core.ping', params: {} }),\n  }).then(x => x.json());\n  return 'result' in r || 'error' in r;\n}","typeGuard":"function isMissingResultEnvelope(err: unknown): boolean {\n  return err instanceof Error && err.message === '[transport:cloud] response missing result';\n}","tryCatchPattern":"try {\n  return await transport.call<T>(method, params);\n} catch (err) {\n  if (isMissingResultEnvelope(err)) {\n    throw new ConfigError(`rpcUrl does not serve raw JSON-RPC 2.0: check gateway/wrapping at ${redact(url)}`);\n  }\n  throw err;\n}","preventionTips":["Probe the URL with core.ping and assert the envelope shape before saving a profile","Never point the transport at API-gateway routes that wrap responses in {success,data}","Keep service workers/edge middleware off POST /rpc"],"tags":["transport","cloud","json-rpc","protocol-violation","gateway"],"backgroundTag":"malformed-json-rpc-response","analyzedSha":"749120085864ce16e0f273c7b86fac7740b39c5b","analyzedAt":"2026-08-17T21:21:45.363Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}