ruvnet/ruflo · error
Rating failed: ${error}
Error message
Rating failed: ${error} What it means
Thrown by rateItem() when the POST to https://us-central1-claude-flow.cloudfunctions.net/publish-registry?action=rate returns a non-2xx status. The raw response body text is embedded in the message, so the Cloud Function's own error (validation, quota, auth) is visible after the 'Rating failed: ' prefix. Note the fetch itself already enforces a 10s AbortSignal timeout, so this error means the server was reached but rejected the request.
Source
Thrown at v3/@claude-flow/cli/src/services/registry-api.ts:81
if (!validateRating(rating)) {
throw new Error('Rating must be integer 1-5');
}
const response = await fetch(`${REGISTRY_API_URL}?action=rate`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
itemId,
rating,
itemType,
...(userId && { userId }),
}),
signal: AbortSignal.timeout(10000),
});
if (!response.ok) {
const error = await response.text();
throw new Error(`Rating failed: ${error}`);
}
return response.json() as Promise<RatingResponse>;
}
/**
* Get ratings for a single item
*/
export async function getRating(
itemId: string,
itemType: 'plugin' | 'model' = 'plugin'
): Promise<RatingResponse> {
if (!validateItemId(itemId)) {
throw new Error('Invalid item ID');
}
const params = new URLSearchParams({
action: 'get-ratings',View on GitHub (pinned to fa13ee4ad6)
Solutions
- Read the text after 'Rating failed: ' — it is the server's response body and names the actual cause (e.g. 'item not found', 'quota exceeded').
- Retry transient 5xx/502/503 with exponential backoff (the fetch already times out at 10s per attempt); do not retry 4xx.
- Verify the itemId exists in the registry (it must have been published, not just installed locally) and that itemType is 'plugin' or 'model'.
- Check network egress: curl -i 'https://us-central1-claude-flow.cloudfunctions.net/publish-registry?action=analytics' — if a proxy page comes back, fix the environment, not the code.
Example fix
// before
try {
await rateItem(pluginId, 5);
} catch (e) {
throw e; // 'Rating failed: <html>Proxy Error...' — opaque
}
// after
try {
await rateItem(pluginId, 5);
} catch (e) {
const msg = e instanceof Error ? e.message : String(e);
if (msg.startsWith('Rating failed: ') && /5\d{2}|quota/i.test(msg)) {
await backoffRetry(() => rateItem(pluginId, 5), { tries: 3 });
} else {
throw e;
}
} Defensive patterns
Strategy: try-catch
Try / catch
try {
return await rateItem(itemId, rating);
} catch (e) {
const msg = e instanceof Error ? e.message : String(e);
if (!msg.startsWith('Rating failed: ')) throw e; // client-side validation → fix input
const serverText = msg.slice('Rating failed: '.length);
if (/^5\d{2}|quota|rate/i.test(serverText)) {
return backoffRetry(() => rateItem(itemId, rating), { tries: 3, baseMs: 500 });
}
throw new Error(`Registry rejected rating: ${serverText}`, { cause: e });
} Prevention
- Treat ratings as best-effort telemetry: catch and log, never let a failed rating break the user flow.
- Verify egress to *.cloudfunctions.net in CI/prod environments (proxy errors appear verbatim in the message).
- Cache the rating UI locally and sync once, instead of posting on every interaction.
- Distinguish client validation errors ('Rating must be integer 1-5', 'Invalid item ID') from server text by message prefix before retrying — only the latter can be transient.
When it happens
Trigger: The Cloud Function returns 4xx for a payload its side rejects (unknown itemId, wrong itemType, malformed userId) or 5xx during a cold start / outage; a corporate proxy or captive portal returns 403/502; the endpoint is rate-limiting your client.
Common situations: CI environments with restricted egress where the proxy answers with an HTML error page (that HTML ends up in the message); rating an itemId that was never published to the registry; Google Cloud Functions cold-start 500s; running during a registry deploy outage.
Related errors
- Failed to get ratings
- Failed to get analytics
- Failed to get bulk ratings
- Failed to fetch ${baseURL}/models: ${response.status} ${resp
- Failed to fetch manifest from ${url}: ${res.status} ${res.st
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/2372ffa6ddfa6960.
Report an issue: GitHub.