vercel/ai · warning · RelayRequestError

Unknown host tool relay endpoint.

Error message

Unknown host tool relay endpoint.

What it means

handleRequest rejects any HTTP request whose method is not POST with this 404 RelayRequestError. The relay only serves POST endpoints (/catalog/next, /catalog/seen, /invoke), so GET/PUT/DELETE requests to any path — including valid paths — are treated as unknown endpoints. It is surfaced to the client as a 404 JSON body with this message.

Source

Thrown at packages/harness-acp/src/v1/bridge/host-tool-relay.ts:161

}

async function handleRequest({
  request,
  credential,
  state,
  serverName,
  turn,
  nextInvocationOrder,
}: {
  request: IncomingMessage;
  credential: string;
  state: CatalogState;
  serverName: string;
  turn: HostToolRelayTurn | undefined;
  nextInvocationOrder: () => number;
}): Promise<unknown> {
  if (request.method !== 'POST') {
    throw new RelayRequestError({
      status: 404,
      message: 'Unknown host tool relay endpoint.',
    });
  }
  if (
    !credentialsMatch({
      expected: credential,
      actual: request.headers.authorization,
    })
  ) {
    throw new RelayRequestError({
      status: 401,
      message: 'Invalid host tool relay credential.',
    });
  }
  const body = await readJSONBody({ request });
  if (request.url === '/catalog/next') {
    return handleCatalogNext({ body, state });

View on GitHub (pinned to 69428b1f8b)

Solutions

  1. Send requests with method POST and a JSON body.
  2. Verify the client library call you use issues POST (e.g. fetch with { method: 'POST' }).
  3. Exclude the relay URL from GET-based health checks or add a dedicated POST-aware probe.
  4. Check the exact request.url you are hitting; the relay only serves /catalog/next, /catalog/seen, and /invoke.

Example fix

// before
const res = await fetch(relayUrl); // GET
// after
const res = await fetch(relayUrl, {
  method: 'POST',
  headers: { authorization: `Bearer ${credential}`, 'content-type': 'application/json' },
  body: JSON.stringify({ requestId, toolName, input, catalogRevision }),
});
Defensive patterns

Strategy: validation

Validate before calling

function assertPost(url: string, init: RequestInit) {
  if ((init.method ?? 'GET').toUpperCase() !== 'POST') {
    throw new Error(`Host tool relay requires POST, got ${init.method ?? 'GET'} for ${url}`);
  }
}

Try / catch

try {
  const res = await fetch(relay.url, { method: 'POST', ... });
  if (!res.ok) {
    const { error } = await res.json();
    throw new Error(`${res.status}: ${error}`);
  }
} catch (error) {
  if (error instanceof Error && error.message.includes('Unknown host tool relay endpoint')) {
    // fix HTTP method to POST and retry once
  }
}

Prevention

When it happens

Trigger: Sending GET /invoke (e.g. opening the URL in a browser or curl without -X POST), a health-check probe hitting the relay URL with GET, or a misconfigured HTTP client using the wrong method against any relay path.

Common situations: Manually testing the relay URL in a browser; load balancer or health checks using GET on the MCP API handler route; SDK code or scripts using the wrong HTTP verb; proxying that strips or rewrites POST to GET on redirects.

Related errors


AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30). Data as JSON: /api/errors/5ac9573f8d749106. Report an issue: GitHub.