ruvnet/ruflo · error
fetchAgentCard: no fetch implementation available
Error message
fetchAgentCard: no fetch implementation available
What it means
fetchAgentCard() needs an HTTP client: options.fetchImpl if provided, otherwise the global globalThis.fetch. When neither is a function it refuses to start the request. This targets runtimes without a built-in WHATWG fetch (Node.js below 18, older jsdom test setups, some bundler/edge configurations).
Source
Thrown at v3/@claude-flow/plugin-agent-federation/src/a2a/consume.ts:49
* URL) gets the A2A well-known path appended; anything already pointing at a
* JSON document is used as-is.
*/
export function resolveAgentCardUrl(baseOrCardUrl: string): string {
const url = new URL(baseOrCardUrl);
if (url.pathname === '/' || url.pathname === '') {
url.pathname = A2A_WELL_KNOWN_PATH;
}
return url.toString();
}
/** Fetch and structurally validate a remote A2A Agent Card. */
export async function fetchAgentCard(
baseOrCardUrl: string,
options: FetchAgentCardOptions = {},
): Promise<FetchAgentCardResult> {
const fetchImpl = options.fetchImpl ?? globalThis.fetch;
if (typeof fetchImpl !== 'function') {
throw new Error('fetchAgentCard: no fetch implementation available');
}
const sourceUrl = resolveAgentCardUrl(baseOrCardUrl);
const maxBytes = options.maxBytes ?? 256 * 1024;
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), options.timeoutMs ?? 10_000);
let text: string;
try {
const res = await fetchImpl(sourceUrl, {
signal: controller.signal,
headers: { accept: 'application/json' },
});
if (!res.ok) {
throw new Error(`fetchAgentCard: ${sourceUrl} returned HTTP ${res.status}`);
}
text = await res.text();
} finally {
clearTimeout(timer);View on GitHub (pinned to fa13ee4ad6)
Solutions
- Pass an implementation explicitly: fetchAgentCard(url, { fetchImpl }) using undici's or node-fetch's fetch
- Upgrade to Node 18+ or a runtime that ships WHATWG fetch
- In tests, inject a stub fetchImpl instead of relying on the global
- If you import a fetch polyfill, make sure it runs before this module is used
Example fix
// before
await fetchAgentCard('https://peer.example');
// after
import { fetch as undiciFetch } from 'undici';
await fetchAgentCard('https://peer.example', { fetchImpl: undiciFetch }); Defensive patterns
Strategy: validation
Validate before calling
const fetchImpl =
typeof globalThis.fetch === 'function'
? globalThis.fetch.bind(globalThis)
: (await import('undici')).fetch;
await fetchAgentCard(url, { fetchImpl }); Type guard
function hasGlobalFetch(): boolean {
return typeof globalThis.fetch === 'function';
} Prevention
- Run on Node 18+ or inject undici/node-fetch explicitly
- In tests, always pass a stub fetchImpl rather than relying on the global
- Check runtime requirements once at process start and fail with a clear message
- Avoid relying on ambient globals in bundled code
When it happens
Trigger: Running on Node 16 or earlier where globalThis.fetch is undefined; test environments (older jsdom) that do not install fetch; bundlers that tree-shake or alias the global away; passing options.fetchImpl that is not a function (e.g. a module object).
Common situations: CI images pinned to old Node LTS versions; Electron renderer or sandboxed contexts without fetch; code reused across Node and restricted runtimes.
Related errors
- String length ${len} exceeds remaining buffer
- Unknown GGUF array element type: ${elemType}
- Unknown GGUF value type: ${valueType}
- Invalid GGUF magic: 0x${magic.toString(16)} (expected 0x4655
- Unsupported GGUF version: ${version} (expected 2 or 3)
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/ef61248f88e9963e.
Report an issue: GitHub.