tinyhumansai/openhuman · error · ValidationError
Invalid ${paramName}: '${value}'. Must be a positive integer
Error message
Invalid ${paramName}: '${value}'. Must be a positive integer. What it means
The string branch of validatePositiveInt(): the value is a string, so it is parsed with Number.parseInt(value, 10); when parsing yields NaN or the result is <= 0 it throws ValidationError "Invalid <param>: '<value>'. Must be a positive integer." Note parseInt('12abc') succeeds as 12 — only fully unparseable or non-positive strings fail.
Source
Thrown at app/src/lib/mcp/validation.ts:86
}
});
}
/**
* Validate a positive integer parameter (e.g. message IDs)
*/
export function validatePositiveInt(value: unknown, paramName: string): number {
if (typeof value === 'number') {
if (!Number.isInteger(value) || value <= 0) {
throw new ValidationError(`Invalid ${paramName}: ${value}. Must be a positive integer.`);
}
return value;
}
if (typeof value === 'string') {
const intValue = Number.parseInt(value, 10);
if (Number.isNaN(intValue) || intValue <= 0) {
throw new ValidationError(`Invalid ${paramName}: '${value}'. Must be a positive integer.`);
}
return intValue;
}
throw new ValidationError(`Invalid ${paramName}: ${String(value)}. Must be a positive integer.`);
}
/**
* Validate optional ID (can be undefined)
*/
export function validateOptionalId(value: unknown, paramName: string): number | string | undefined {
if (value === undefined || value === null) {
return undefined;
}
return validateId(value, paramName);
}
View on GitHub (pinned to 7491200858)
Solutions
- Send the exact numeric string without decoration; strip separators/whitespace and validate with /^\d+$/ and > 0 before calling.
- Coerce at the boundary: const n = Number(value); if (Number.isInteger(n) && n > 0) use n.
- Reject empty inputs in the form layer so '' never reaches the validator.
- For IDs that legitimately contain letters, this validator is wrong — use validateId() (int-or-username) instead.
Example fix
// before
await tool({ message_id: el.dataset.id }); // may be '' or 'msg-7'
// after
const raw = el.dataset.id ?? '';
if (!/^\d+$/.test(raw) || Number(raw) < 1) throw new UserInputError('Pick a valid message');
await tool({ message_id: Number(raw) }); Defensive patterns
Strategy: validation
Validate before calling
const m = /^\d+$/.exec(raw ?? '');
const id = m && Number(m[0]) > 0 ? Number(m[0]) : undefined;
if (id === undefined) throw new UserInputError('Expected a positive integer string');
await tool({ message_id: id }); Type guard
function isPositiveIntString(v: unknown): v is string {
return typeof v === 'string' && /^\d+$/.test(v) && Number(v) > 0;
} Try / catch
try {
validatePositiveInt(value, 'cursor');
} catch (err) {
if (err instanceof ValidationError) {
return badRequest(err.message); // surface to tool caller as 400
}
throw err;
} Prevention
- Reject empty strings and decorated numerals at the form layer.
- Convert DOM/query-string IDs to numbers at the boundary.
- Remember parseInt tolerates trailing junk ('12abc') — validate with ^\d+$ if strictness matters.
When it happens
Trigger: Passing a string param that is empty, non-numeric ('abc', 'id-42'), a float string parsing to <= 0 ('0', '-3'), or numeric-prefixed junk ('x9'). Common when IDs come from URL/query params, DOM datasets, or user input without validation.
Common situations: Tool invoked from a web UI where IDs are strings from the DOM; empty-string defaults leaking from forms; locale-formatted numbers ('1,000') failing parseInt; trailing whitespace usually tolerable but embedded letters fail.
Related errors
- Invalid ${paramName}: ${value}. Must be a positive integer.
- Invalid ${paramName}: ${String(value)}. Must be a positive i
- "{key}" is required
- mascot manifest: missing mascots array
- mascot manifest: no renderable mascots
AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17).
Data as JSON: /api/errors/d4deeccf191ebd6f.
Report an issue: GitHub.