{"record":{"id":"f13b9720a521f540","repo":"tinyhumansai/openhuman","slug":"unknown-core-rpc-error","errorCode":null,"errorMessage":"Unknown core RPC error","messagePattern":"Unknown core RPC error","errorType":"exception","errorClass":"CoreRpcError","httpStatus":null,"severity":"error","filePath":"app/src/services/coreRpcClient.ts","lineNumber":772,"sourceCode":"        error: json.error,\n      });\n      const rawMessage = json.error.message || 'Core RPC returned an error';\n      const kind = classifyRpcError(rawMessage, undefined, json.error.data);\n      if (kind === 'auth_expired' && !suppressAuthExpiredEvent)\n        dispatchAuthExpired(payload.method, classifyAuthExpiredReason(rawMessage, undefined));\n      throw new CoreRpcError(rawMessage, kind, undefined, json.error.data);\n    }\n    if (!Object.prototype.hasOwnProperty.call(json, 'result')) {\n      throw new Error('Core RPC response missing result');\n    }\n\n    coreRpcLog('HTTP response', { id: payload.id, method: payload.method });\n    return json.result as T;\n  } catch (err) {\n    coreRpcError('Core RPC call failed', sanitizeError(err));\n    if (err instanceof CoreRpcError) throw err;\n    const message = coreRpcErrorMessage(err);\n    throw new CoreRpcError(message, classifyRpcError(message));\n  }\n}\n","sourceCodeStart":754,"sourceCodeEnd":775,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/749120085864ce16e0f273c7b86fac7740b39c5b/app/src/services/coreRpcClient.ts#L754-L775","documentation":"The catch-all re-wrap at the bottom of callCoreRpc: something was thrown inside the call flow that was not a CoreRpcError and had no extractable message. coreRpcErrorMessage tries Error.message, bare strings, then object .message/.error fields; 'Unknown core RPC error' means the thrown value was none of those (e.g. undefined/null, a number, an opaque cross-realm object, or an object with an empty message). The original value is logged via coreRpcError('Core RPC call failed', sanitizeError(err)) before re-throwing.","triggerScenarios":"A rejection with a non-Error value: Promise.reject(undefined), throwing a plain object without message/error keys, an aborted fetch surfacing as an opaque object, or custom fetch wrappers/interceptors rejecting with status codes. Anything that escapes earlier branches (network 'Failed to fetch' keeps its own message; this is for message-less throws).","commonSituations":"Interceptors (Sentry/fetch shim, offline queues) rejecting with non-Error values; webview-specific fetch implementations throwing DOMException-like objects whose message is empty in release builds; test code rejecting with plain values.","solutions":["Enable the debug logger (DEBUG='core-rpc:error') to see the sanitized original err in 'Core RPC call failed' — the classification is only as good as what was thrown","Find and fix the layer rejecting with a non-Error: make it throw new Error(...) or reject with an Error so a real message propagates","Grep custom fetch middleware / offline shims installed in the webview for bare rejects","If it correlates with going offline, treat kind via classifyRpcError on the message-less path and add a connectivity check before calling"],"exampleFix":"// before (a fetch shim rejecting bare)\nif (!navigator.onLine) reject(undefined);\n\n// after\nif (!navigator.onLine) reject(new Error('offline: network unavailable'));","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function isWrappedUnknownCoreError(err: unknown): boolean {\n  return err instanceof Error && err.message === 'Unknown core RPC error';\n}","tryCatchPattern":"try {\n  return await callCoreRpc({ method, params });\n} catch (err) {\n  if (isWrappedUnknownCoreError(err)) {\n    // enable DEBUG='core-rpc:error' — the sanitized original is logged as 'Core RPC call failed'\n    logger.error('core RPC threw a message-less value; enable core-rpc:error to inspect', { method });\n  }\n  throw err;\n}","preventionTips":["Always reject/throw Error objects from fetch shims and interceptors — never bare values","Keep DEBUG='core-rpc:error' available in dev builds to recover the original thrown value","Don't build control flow on this message — fix the throwing layer instead"],"tags":["rpc","non-error-throw","catch-all","diagnostics"],"backgroundTag":"non-error-throw","analyzedSha":"749120085864ce16e0f273c7b86fac7740b39c5b","analyzedAt":"2026-08-17T21:21:45.363Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}