|
1 | 1 | import { RpcService } from '@metamask/kernel-rpc-methods'; |
2 | 2 | import type { KernelDatabase } from '@metamask/kernel-store'; |
3 | 3 | import type { Kernel } from '@metamask/ocap-kernel'; |
| 4 | +import { kunser } from '@metamask/ocap-kernel'; |
4 | 5 | import { rpcHandlers } from '@metamask/ocap-kernel/rpc'; |
5 | 6 | import { unlink } from 'node:fs/promises'; |
6 | 7 | import { createServer } from 'node:net'; |
@@ -186,12 +187,47 @@ async function processRequest( |
186 | 187 | return { jsonrpc: '2.0', id, result: result ?? null }; |
187 | 188 | } catch (error) { |
188 | 189 | const code = isRpcError(error) ? error.code : -32603; |
189 | | - const message = error instanceof Error ? error.message : 'Internal error'; |
| 190 | + const message = extractErrorMessage(error); |
190 | 191 |
|
191 | 192 | return { jsonrpc: '2.0', id, error: { code, message } }; |
192 | 193 | } |
193 | 194 | } |
194 | 195 |
|
| 196 | +/** |
| 197 | + * Extract a human-readable message from an unknown thrown value. |
| 198 | + * |
| 199 | + * Handles two cases: |
| 200 | + * - `Error` instances: use `error.message` directly. |
| 201 | + * - CapData objects: vat rejections propagate as serialised CapData; deserialise |
| 202 | + * with `kunser` and extract the message if the result is an Error. |
| 203 | + * - Everything else: fall back to `'Internal error'`. |
| 204 | + * |
| 205 | + * @param error - The caught value. |
| 206 | + * @returns A string suitable for the JSON-RPC error `message` field. |
| 207 | + */ |
| 208 | +function extractErrorMessage(error: unknown): string { |
| 209 | + if (error instanceof Error) { |
| 210 | + return error.message; |
| 211 | + } |
| 212 | + // Vat rejections arrive as CapData objects: { body: string, slots: unknown[] } |
| 213 | + if ( |
| 214 | + typeof error === 'object' && |
| 215 | + error !== null && |
| 216 | + 'body' in error && |
| 217 | + 'slots' in error |
| 218 | + ) { |
| 219 | + try { |
| 220 | + const deserialized = kunser(error as Parameters<typeof kunser>[0]); |
| 221 | + if (deserialized instanceof Error) { |
| 222 | + return deserialized.message; |
| 223 | + } |
| 224 | + } catch { |
| 225 | + // Fall through to default |
| 226 | + } |
| 227 | + } |
| 228 | + return 'Internal error'; |
| 229 | +} |
| 230 | + |
195 | 231 | /** |
196 | 232 | * Check if an error is an RPC error with a numeric code. |
197 | 233 | * |
|
0 commit comments