different-ai/openwork · error · SafeProbeFailure

invalid_jsonrpc_envelope

invalid_jsonrpc_envelope

Error message

invalid_jsonrpc_envelope

What it means

parseJsonRpcResult validates the decoded JSON-RPC payload envelope and throws SafeProbeFailure("invalid_jsonrpc_envelope") at line 529 when the payload is not an object or its 'jsonrpc' field is not exactly "2.0". The probe only accepts well-formed JSON-RPC 2.0 responses. A second throw of the same code (line 533) fires when 'result' is missing or not an object.

Solutions

  1. Confirm the probe URL points at the MCP endpoint that speaks JSON-RPC 2.0
  2. Make the server include "jsonrpc":"2.0" in every response
  3. Inspect the raw response body to see what the server actually returned
  4. Check for a reverse proxy serving an error/config page at that path

Example fix

// before
{"id":1,"result":{...}}
// after
{"jsonrpc":"2.0","id":1,"result":{...}}
Defensive patterns

Strategy: type-guard

Validate before calling

const body = JSON.parse(raw);
if (typeof body !== "object" || body === null || (body as Record<string, unknown>).jsonrpc !== "2.0") {
  throw new Error("endpoint response is not JSON-RPC 2.0");
}

Type guard

function isJsonRpc2Envelope(v: unknown): v is { jsonrpc: "2.0"; id: unknown } & Record<string, unknown> {
  return typeof v === "object" && v !== null && (v as Record<string, unknown>).jsonrpc === "2.0";
}

Try / catch

try {
  const result = parseJsonRpcResult(payload, requestId);
} catch (e) {
  if (e instanceof SafeProbeFailure && e.code === "invalid_jsonrpc_envelope") {
    console.error("endpoint did not return a JSON-RPC 2.0 envelope", rawBody);
  } else throw e;
}

Prevention

When it happens

Trigger: Endpoint returns a JSON body that is not an object (array/string/number/null), or an object whose jsonrpc field is absent or not "2.0".

Common situations: Hitting a non-MCP REST endpoint at the probe URL; server implements an older/different JSON-RPC dialect (e.g. jsonrpc "1.0" or omitted field); a gateway error page returning JSON but not JSON-RPC.

Related errors


AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01). Data as JSON: /api/errors/9feab5f293ab2e3f. Report an issue: GitHub.

Appendix: source

Thrown at apps/server/src/agent-context-cloud-probe.ts:529

      dispatch();
      continue;
    }
    if (line.startsWith(":")) continue;
    const colon = line.indexOf(":");
    const field = colon < 0 ? line : line.slice(0, colon);
    const rawValue = colon < 0 ? "" : line.slice(colon + 1);
    const value = rawValue.startsWith(" ") ? rawValue.slice(1) : rawValue;
    if (field === "event") event = value;
    if (field === "data") data.push(value);
  }
  dispatch();
  if (messages.length !== 1) throw new SafeProbeFailure("invalid_json");
  return messages[0];
}

function parseJsonRpcResult(payload: unknown, requestId: string): Record<string, unknown> {
  if (!isRecord(payload) || payload.jsonrpc !== "2.0") {
    throw new SafeProbeFailure("invalid_jsonrpc_envelope");
  }
  if (Object.hasOwn(payload, "error")) throw new SafeProbeFailure("jsonrpc_error");
  if (payload.id !== requestId) throw new SafeProbeFailure("request_id_mismatch");
  if (!isRecord(payload.result)) throw new SafeProbeFailure("invalid_jsonrpc_envelope");
  return payload.result;
}

function requireSupportedProtocolVersion(initializeResult: Record<string, unknown>): void {
  const version = initializeResult.protocolVersion;
  if (typeof version !== "string" || version.length === 0 || version.length > MAX_PROTOCOL_HEADER_LENGTH) {
    throw new SafeProbeFailure("invalid_jsonrpc_envelope");
  }
  if (version !== MCP_PROTOCOL_VERSION) throw new SafeProbeFailure("unsupported_protocol_version");
}

function validateCatalog(rpcResult: Record<string, unknown>): { toolIds: string[]; totalToolCount: number } {
  if (rpcResult.nextCursor !== undefined && rpcResult.nextCursor !== null) {
    throw new SafeProbeFailure("pagination_unsupported");

View on GitHub (pinned to 2b7df46e8a)