{"record":{"id":"267368510e7a34c0","repo":"tinyhumansai/openhuman","slug":"transport-local-http-response-status-text","errorCode":null,"errorMessage":"[transport:local] HTTP ${response.status}: ${text || response.statusText}","messagePattern":"\\[transport:local\\] HTTP (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/src/services/transport/LocalTransport.ts","lineNumber":77,"sourceCode":"    try {\n      response = await fetch(rpcUrl, {\n        method: 'POST',\n        headers,\n        body: JSON.stringify(payload),\n        signal: controller.signal,\n      });\n    } catch (err) {\n      if (controller.signal.aborted) {\n        throw new Error(`[transport:local] ${method} timed out after ${this.timeoutMs}ms`);\n      }\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:local] 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:local] ← %s error: %s', method, json.error.message);\n      throw new Error(json.error.message ?? 'Core RPC returned an error');\n    }\n    if (!Object.prototype.hasOwnProperty.call(json, 'result')) {\n      throw new Error('[transport:local] response missing result');\n    }\n\n    log('[transport:local] ← %s id=%d ok', method, id);\n    return json.result as T;\n  }\n\n  async *stream<T>(\n    method: string,","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/749120085864ce16e0f273c7b86fac7740b39c5b/app/src/services/transport/LocalTransport.ts#L59-L95","documentation":"LocalTransport surfaces any non-2xx HTTP status from the local core's /rpc endpoint with this message, appending the response body text when present. The status code carries the real diagnosis: 401 means the Bearer token was missing/wrong, 404 means the URL/port is wrong, 5xx means the core itself failed while handling the call.","triggerScenarios":"401 when the cached per-launch hex bearer token is stale (it rotates every core launch and is delivered in-memory via the core_rpc_token Tauri command); 404 when getCoreRpcUrl() resolved to a dead port; 500 when the Rust handler panicked; 502/503 when something proxies the loopback URL.","commonSituations":"Core restarted between token fetch and call; OPENHUMAN_CORE_REUSE_EXISTING=1 attaching to a core launched with a different token; standalone debugging with ./target/debug/openhuman-core serve while the app still holds the previous session's token (read {workspace}/core.token for that mode).","solutions":["Re-resolve URL and token per call window via the core_rpc_url / core_rpc_token Tauri commands instead of caching them","For 401 against a standalone core, read the current token from {workspace}/core.token or set OPENHUMAN_CORE_TOKEN","For 404/connrefused-style bodies, restart the core process (restart_core_process) so a fresh listener binds","Read the appended body text — the core's error payload names the failing handler"],"exampleFix":"// before\nconst token = cachedToken; // fetched once at boot\n// after\nconst token = await invoke<string>('core_rpc_token'); // per-launch, re-fetch after core restarts","handlingStrategy":"try-catch","validationCode":"// Refresh per-launch credentials before long batches:\nconst rpcUrl = await invoke<string>('core_rpc_url');\nconst token = await invoke<string>('core_rpc_token');\nif (!rpcUrl || !token) throw new Error('core not ready');","typeGuard":null,"tryCatchPattern":"try {\n  await local.call(method, params);\n} catch (err) {\n  const m = err instanceof Error ? err.message : '';\n  if (m.includes('HTTP 401')) { /* re-fetch token, retry once */ }\n  else if (m.includes('HTTP 404')) { /* re-fetch rpcUrl (port rotated), retry once */ }\n  else throw err; // 5xx: surface core error text that follows 'HTTP 500'\n}","preventionTips":["Never cache the bearer token across core restarts — it rotates every launch","After restart_core_process, re-resolve both core_rpc_url and core_rpc_token before the next RPC","In tests, assert on the status embedded in the message ('HTTP 401') rather than exact strings"],"tags":["http","transport","local-core","authentication","json-rpc"],"backgroundTag":"http-error-response","analyzedSha":"749120085864ce16e0f273c7b86fac7740b39c5b","analyzedAt":"2026-08-17T21:21:45.363Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}