{"record":{"id":"d776643f4f11cdf5","repo":"ruvnet/ruflo","slug":"x-ruv-io-payload-error-message-rpc-error","errorCode":null,"errorMessage":"x.ruv.io: ${payload.error.message ?? 'rpc error'}","messagePattern":"x\\.ruv\\.io: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/cli/src/mcp-tools/x-federation-tools.ts","lineNumber":30,"sourceCode":"// ADR-125 precedence: the tool arg `gatewayUrl` (fed by `ruflo federation --gateway`)\n// takes precedence over the RUFLO_X_GATEWAY_URL env var, which precedes the default.\nconst GATEWAY = (override?: unknown): string =>\n  ((typeof override === 'string' && override) || process.env.RUFLO_X_GATEWAY_URL || 'https://x.ruv.io').replace(/\\/$/, '');\nconst gatewayArg = { gatewayUrl: { type: 'string', description: 'Gateway base URL; takes precedence over RUFLO_X_GATEWAY_URL (default https://x.ruv.io).' } } as const;\nconst TIMEOUT_MS = 25_000;\n\n/** Minimal MCP-over-Streamable-HTTP client: POST JSON-RPC, parse the SSE `data:` frame. */\nasync function gatewayRpc(method: string, params: Record<string, unknown>, gatewayUrl?: unknown): Promise<unknown> {\n  const res = await fetch(`${GATEWAY(gatewayUrl)}/mcp`, {\n    method: 'POST',\n    headers: { 'content-type': 'application/json', accept: 'application/json, text/event-stream' },\n    body: JSON.stringify({ jsonrpc: '2.0', id: Date.now(), method, params }),\n    signal: AbortSignal.timeout(TIMEOUT_MS),\n  });\n  const text = await res.text();\n  const line = text.split('\\n').find((l) => l.startsWith('data:'));\n  const payload = JSON.parse(line ? line.slice(5) : text) as { result?: unknown; error?: { message?: string } };\n  if (payload.error) throw new Error(`x.ruv.io: ${payload.error.message ?? 'rpc error'}`);\n  return payload.result;\n}\n/**\n * Relay-sourced gateway responses are not bare JSON. Since #3300 the gateway\n * wraps anything published by other federation members in a provenance envelope\n * (plugins/ruflo-x-gateway/src/untrusted.mjs): several lines of gateway-authored\n * prose, then the JSON body between a matched\n * `<<<UNTRUSTED_RELAY_DATA <uuid>>>>` / `<<<END_UNTRUSTED_RELAY_DATA <uuid>>>>`\n * pair. `JSON.parse` on the whole string fails on the first prose word, which is\n * the `Unexpected token 'T', \"The block \"...` seen from every federation read.\n *\n * Three things keep a publisher from closing the block early, and it is worth\n * being precise about which one is doing the work today:\n *   1. The body is JSON.stringify'd, so it is a SINGLE line — a publisher's text\n *      cannot contain a raw newline, and the markers below are newline-anchored.\n *      This is what actually neutralises forged markers in relay content today.\n *   2. The token backreference: a forged END carrying any other token does not\n *      terminate the region. This is the defence that survives (1) — if the body","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/ruvnet/ruflo/blob/9c61c86f06b439af2a95085ae9bb0ca839662e41/v3/@claude-flow/cli/src/mcp-tools/x-federation-tools.ts#L12-L48","documentation":"Thrown by `gatewayRpc` when the x.ruv.io gateway's JSON-RPC response contains an `error` object. The gateway accepted the transport (an HTTP response arrived and parsed) but rejected the RPC call itself — e.g. unknown method, invalid params, or the remote tool raised an error. The gateway's error message is interpolated; 'rpc error' is the fallback when the error object has no message.","triggerScenarios":"Any gateway-backed call (`gatewayTool`, `gatewayResource`) whose `tools/call` or `resources/read` JSON-RPC response carries `error`: calling a tool name the gateway does not expose, malformed arguments failing remote schema validation, gateway-internal exceptions, or admin-gated operations invoked without a valid token. Also produced when the SSE-style response has no `data:` line and the raw body parses to a JSON-RPC error.","commonSituations":"A stale or custom `gatewayUrl` pointing at an incompatible gateway version; the gateway deploying a renamed tool (e.g. `federation_publish` changed); passing `arguments` that fail the remote inputSchema; the gateway being degraded/overloaded and returning structured errors; network proxies returning JSON error bodies instead of results.","solutions":["Read the interpolated gateway message — it usually names the failing tool or parameter — and correct the tool name/arguments accordingly.","Verify `gatewayUrl` (or the default x.ruv.io endpoint) is current and the gateway version supports the method being called.","Re-run after checking gateway health/status; transient gateway errors may clear on retry.","If the error is auth-related, set RUFLO_X_ADMIN_TOKEN for admin-gated tools like `x_federation_publish`.","Log the full JSON-RPC payload (result vs error) when debugging, since the thrown message can be the generic 'rpc error' fallback."],"exampleFix":"// before: silently assuming the call succeeded shape-wise\nconst r = await gatewayTool('federation_publish', args);\n// after: pass a valid gatewayUrl and catch the RPC error for diagnostics\ntry {\n  const r = await gatewayTool('federation_publish', { ...args, gatewayUrl: 'https://x.ruv.io' });\n} catch (e) {\n  console.error('gateway rpc failed:', (e as Error).message);\n}","handlingStrategy":"try-catch","validationCode":"const url = (args.gatewayUrl as string) ?? 'https://x.ruv.io';\ntry { new URL(url); } catch { throw new Error(`invalid gatewayUrl: ${url}`); }\nif (!args.name || typeof args.name !== 'string') throw new Error('gateway tool name is required');","typeGuard":"function isRpcPayload(p: unknown): p is { result?: unknown; error?: { message?: string } } {\n  return typeof p === 'object' && p !== null && ('result' in p || 'error' in p);\n}","tryCatchPattern":"try {\n  const result = await gatewayRpc('tools/call', { name, arguments }, gatewayUrl);\n} catch (e) {\n  if (e instanceof Error && e.message.startsWith('x.ruv.io:')) {\n    console.error('gateway rejected the RPC:', e.message);\n    // check gatewayUrl/version, auth, and arguments before retrying\n  } else throw e;\n}","preventionTips":["Pin and periodically verify the gatewayUrl points at a compatible gateway version.","Validate tool arguments against the tool's inputSchema before remote calls.","Log full JSON-RPC error bodies when debugging, since the message can be the generic 'rpc error'.","Set RUFLO_X_ADMIN_TOKEN for admin-gated methods before calling.","Monitor gateway health/status endpoints and back off on degradation."],"tags":["json-rpc","gateway","federation","remote-error"],"backgroundTag":"api-error-response","analyzedSha":"9c61c86f06b439af2a95085ae9bb0ca839662e41","analyzedAt":"2026-09-22T05:44:27.648Z","contentChangedAt":"2026-09-22T05:44:27.648Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}