ruvnet/ruflo · error
fetchAgentCard: ${sourceUrl} returned HTTP ${res.status}
Error message
fetchAgentCard: ${sourceUrl} returned HTTP ${res.status} What it means
The Agent Card HTTP request completed at the transport layer but the response status was outside 2xx (res.ok false). The body is never read; instead the resolved source URL and the HTTP status are reported. Note the request already carries an accept: application/json header and a default 10s abort timeout, so this error is purely about the server's status code.
Source
Thrown at v3/@claude-flow/plugin-agent-federation/src/a2a/consume.ts:63
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);
}
if (text.length > maxBytes) {
throw new Error(`fetchAgentCard: card exceeds ${maxBytes} bytes`);
}
let parsed: unknown;
try {
parsed = JSON.parse(text);
} catch {
throw new Error(`fetchAgentCard: ${sourceUrl} did not return valid JSON`);
}
const validation = validateAgentCard(parsed);
if (!validation.valid) {View on GitHub (pinned to fa13ee4ad6)
Solutions
- Open the exact sourceUrl from the error message with curl or a browser and confirm the card is served
- Fix scheme/host/path — remember the resolver appends the well-known path when you pass a base URL
- For 401/403 supply the auth the peer's edge requires or get your egress IP whitelisted
- Retry transient 5xx with backoff; the call is a plain fetch you control, so wrap it in your own retry loop
Example fix
// before
const { card } = await fetchAgentCard(peerUrl);
// after
let card;
for (let i = 0; i < 3; i++) {
try { card = (await fetchAgentCard(peerUrl)).card; break; }
catch (e) {
if (!String(e).includes('HTTP 5') || i === 2) throw e;
await new Promise(r => setTimeout(r, 2 ** i * 250));
}
} Defensive patterns
Strategy: retry
Validate before calling
// pre-flight the URL cheaply before the card fetch
try {
const u = new URL(base);
await fetch(u.origin, { method: 'HEAD' });
} catch {
throw new Error('peer origin unreachable: ' + base);
} Try / catch
for (let attempt = 0; attempt < 3; attempt++) {
try {
return await fetchAgentCard(url, opts);
} catch (e) {
const msg = String(e);
const transient = msg.includes('HTTP 5') || msg.includes('HTTP 429');
if (!transient || attempt === 2) throw e;
await new Promise(r => setTimeout(r, 2 ** attempt * 250));
}
} Prevention
- Verify the well-known card URL with curl when onboarding a peer
- Treat 4xx (other than 429) as permanent config errors, not retries
- Monitor peer availability and cache validated cards with a TTL
- Log the resolved sourceUrl on every failure for quick diagnosis
When it happens
Trigger: Wrong base URL where the well-known agent.json path is not served (404); the peer or an intermediary requires authentication (401/403); reverse proxy misroute or upstream down (502/503); the card endpoint moved without a redirect.
Common situations: Typo'd or stale peer hostname; peer deployed behind a gateway needing a path prefix; transient 5xx while the peer redeploys; firewall returning 403 for unknown egress IPs.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- Failed to fetch ${baseURL}/models: ${response.status} ${resp
- Failed to fetch manifest from ${url}: ${res.status} ${res.st
- PRIVATE_ADDRESS
- Rating failed: ${error}
- Failed to get ratings
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/430673c20c77ce8d.
Report an issue: GitHub.