{"record":{"id":"480dcc91bc95bab0","repo":"tinyhumansai/openhuman","slug":"core-rpc-returned-an-error","errorCode":null,"errorMessage":"Core RPC returned an error","messagePattern":"Core RPC returned an error","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/src/services/api/providerSurfacesApi.ts","lineNumber":18,"sourceCode":"import type { RespondQueueList } from '../../types/providerSurfaces';\nimport { callCoreRpc } from '../coreRpcClient';\n\ninterface ProviderSurfacesQueueEnvelope {\n  data?: RespondQueueList;\n  result?: { data?: RespondQueueList };\n}\n\nconst EMPTY_QUEUE: RespondQueueList = { items: [], count: 0 };\n\nfunction parseQueueEnvelope(raw: unknown): RespondQueueList {\n  if (!raw || typeof raw !== 'object') {\n    throw new Error('provider_surfaces_list_queue: unexpected empty response');\n  }\n\n  const envelope = raw as ProviderSurfacesQueueEnvelope & { error?: { message?: string } };\n  if (envelope.error) {\n    throw new Error(envelope.error.message ?? 'Core RPC returned an error');\n  }\n  const candidate = envelope.result?.data ?? envelope.data;\n  if (!candidate || !Array.isArray(candidate.items) || typeof candidate.count !== 'number') {\n    return EMPTY_QUEUE;\n  }\n  return candidate;\n}\n\nexport const providerSurfacesApi = {\n  async listQueue(): Promise<RespondQueueList> {\n    const raw = await callCoreRpc<unknown>({ method: 'openhuman.provider_surfaces_list_queue' });\n    return parseQueueEnvelope(raw);\n  },\n};\n","sourceCodeStart":1,"sourceCodeEnd":33,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/a221052e0df5b1f7598fceba7329fd1af95d6699/app/src/services/api/providerSurfacesApi.ts#L1-L33","documentation":"Thrown by parseQueueEnvelope() when the payload is an object carrying an 'error' property whose 'message' is missing — the ?? fallback text 'Core RPC returned an error' is used. This is a core-side failure that arrived wrapped inside a success-shaped response (envelope.error) instead of the JSON-RPC error channel that coreRpcClient would have converted to a CoreRpcError, so the original error detail is lost.","triggerScenarios":"The relayed response for provider_surfaces_list_queue is {error: {}} or {error: {code: ...}} with no message — e.g. a Tauri relay_http_rpc wrapping an internal failure, or a core controller embedding a serialized error struct into its result.","commonSituations":"Core crashed or store locked while answering and the shell relays an error object without a message; older core whose error serialization omitted message; nested/double-wrapped envelopes from transport shims.","solutions":["Log the full envelope.error (code/data fields), not just the message, to recover the real failure","Check the core logs at the request timestamp — the underlying error is usually visible core-side","Restart the core; a wedged respond-queue store often clears on a fresh process","If developing the client, include code/data in the thrown message: envelope.error.message ?? `${envelope.error.code}` ?? fallback"],"exampleFix":"// before\nthrow new Error(envelope.error.message ?? 'Core RPC returned an error');\n\n// after\nconst e = envelope.error;\nthrow new Error(e?.message ?? `Core RPC error ${e?.code ?? 'unknown'} ${JSON.stringify(e?.data ?? '')}`.trim());","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function isCoreErrorEnvelope(v: unknown): v is { error: { message?: string; code?: number; data?: unknown } } {\n  return !!v && typeof v === 'object' && 'error' in (v as Record<string, unknown>);\n}","tryCatchPattern":"try {\n  const queue = await providerSurfacesApi.listQueue();\n} catch (e) {\n  // The thrown message is generic; capture the envelope yourself for diagnostics\n  log.error('provider_surfaces_list_queue failed', { error: e });\n  if (e instanceof Error && e.message === 'Core RPC returned an error') {\n    checkCoreLogsAndRestart(); // message-less error envelope — inspect core side\n  } else throw e;\n}","preventionTips":["Preserve code/data from error envelopes when wrapping RPC errors","Keep core logs correlated by request id so message-less errors are traceable","Restart-once policy: a wedged store usually clears with a core restart"],"tags":["rpc","error-envelope","provider-surfaces","diagnostics"],"backgroundTag":null,"analyzedSha":"a221052e0df5b1f7598fceba7329fd1af95d6699","analyzedAt":"2026-08-16T12:47:06.542Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}