ruvnet/ruflo · warning
Rating must be integer 1-5
Error message
Rating must be integer 1-5
What it means
Thrown by rateItem() in the registry API client before any network call: the rating argument failed validateRating(), which requires Number.isInteger(rating) and a value in [1, 5]. This is a client-side input-validation guard protecting the Cloud Functions rating endpoint from garbage input. It fires synchronously, so no HTTP request is wasted.
Source
Thrown at v3/@claude-flow/cli/src/services/registry-api.ts:64
*/
function validateRating(rating: number): boolean {
return Number.isInteger(rating) && rating >= 1 && rating <= 5;
}
/**
* Rate a plugin or model
*/
export async function rateItem(
itemId: string,
rating: number,
itemType: 'plugin' | 'model' = 'plugin',
userId?: string
): Promise<RatingResponse> {
if (!validateItemId(itemId)) {
throw new Error('Invalid item ID');
}
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}`);
}View on GitHub (pinned to fa13ee4ad6)
Solutions
- Convert the input with Number() (or parseInt with radix 10) before calling rateItem, then verify Number.isInteger and the 1–5 range yourself and show a friendly message.
- If your UI uses a different scale (e.g. 0–10), map it to 1–5 before calling (Math.max(1, Math.min(5, Math.round(value / 2)))).
- Constrain the input at the source: HTML <input type="number" min="1" max="5" step="1"> or an enum of literal 1|2|3|4|5.
- Add boundary tests for 0, 1, 5, 6, '3', 3.5 so regressions in parsing surface locally instead of from the library.
Example fix
// before
const rating = parseFloat(args['--rating']); // '4.5' or '0' → throws 'Rating must be integer 1-5'
await rateItem(pluginId, rating);
// after
const rating = Number(args['--rating']);
if (!Number.isInteger(rating) || rating < 1 || rating > 5) {
throw new RangeError(`Invalid rating '${args['--rating']}': must be an integer 1-5`);
}
await rateItem(pluginId, rating); Defensive patterns
Strategy: validation
Validate before calling
const isValidRating = (r: unknown): r is number =>
typeof r === 'number' && Number.isInteger(r) && r >= 1 && r <= 5;
// before calling rateItem:
if (!isValidRating(rawRating)) {
throw new RangeError(`Rating must be integer 1-5, got ${JSON.stringify(rawRating)}`);
}
await rateItem(itemId, rawRating, 'plugin'); Type guard
function isValidRating(r: unknown): r is number {
return typeof r === 'number' && Number.isInteger(r) && r >= 1 && r <= 5;
} Try / catch
try {
await rateItem(itemId, rating);
} catch (e) {
if (e instanceof Error && e.message === 'Rating must be integer 1-5') {
// re-prompt the user / normalize input, then retry once
} else throw e;
} Prevention
- Parse rating input with Number() at the boundary and reject non-integers there with a domain-specific error.
- Constrain the UI: <input type="number" min="1" max="5" step="1"> or a 1–5 star control.
- Type the parameter as 1|2|3|4|5 (union of literals) so invalid values fail at compile time.
- Unit-test boundaries 0, 1, 5, 6, '3', 3.5, NaN against your own guard before wiring the API.
When it happens
Trigger: Calling rateItem(itemId, rating) with a non-integer number (4.5, NaN, Infinity), an out-of-range integer (0, 6, 10), a numeric string ('4' — fails Number.isInteger), or a value parsed from a star-widget UI that yields 0 on empty selection.
Common situations: Rating comes from a form/CLI flag as a string and is passed without Number() conversion; UI uses a 0–10 or 0–100 scale while the API expects 1–5; parseFloat('4.5') on a half-star widget; passing a default of 0 or -1 when the user skipped the rating.
Related errors
- Invalid item ID: ${id}
- Validation failed: ${result.error}
- Rating failed: ${error}
- Invalid worker type
- ${label} must be a canonical unsigned decimal integer
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/bff5951a67f0b9db.
Report an issue: GitHub.