{"record":{"id":"d4deeccf191ebd6f","repo":"tinyhumansai/openhuman","slug":"invalid-paramname-value-must-be-a-positi","errorCode":null,"errorMessage":"Invalid ${paramName}: '${value}'. Must be a positive integer.","messagePattern":"Invalid (.+?): '(.+?)'\\. Must be a positive integer\\.","errorType":"validation","errorClass":"ValidationError","httpStatus":null,"severity":"error","filePath":"app/src/lib/mcp/validation.ts","lineNumber":86,"sourceCode":"    }\n  });\n}\n\n/**\n * Validate a positive integer parameter (e.g. message IDs)\n */\nexport function validatePositiveInt(value: unknown, paramName: string): number {\n  if (typeof value === 'number') {\n    if (!Number.isInteger(value) || value <= 0) {\n      throw new ValidationError(`Invalid ${paramName}: ${value}. Must be a positive integer.`);\n    }\n    return value;\n  }\n\n  if (typeof value === 'string') {\n    const intValue = Number.parseInt(value, 10);\n    if (Number.isNaN(intValue) || intValue <= 0) {\n      throw new ValidationError(`Invalid ${paramName}: '${value}'. Must be a positive integer.`);\n    }\n    return intValue;\n  }\n\n  throw new ValidationError(`Invalid ${paramName}: ${String(value)}. Must be a positive integer.`);\n}\n\n/**\n * Validate optional ID (can be undefined)\n */\nexport function validateOptionalId(value: unknown, paramName: string): number | string | undefined {\n  if (value === undefined || value === null) {\n    return undefined;\n  }\n  return validateId(value, paramName);\n}\n","sourceCodeStart":68,"sourceCodeEnd":103,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/749120085864ce16e0f273c7b86fac7740b39c5b/app/src/lib/mcp/validation.ts#L68-L103","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nawait tool({ message_id: el.dataset.id }); // may be '' or 'msg-7'\n\n// after\nconst raw = el.dataset.id ?? '';\nif (!/^\\d+$/.test(raw) || Number(raw) < 1) throw new UserInputError('Pick a valid message');\nawait tool({ message_id: Number(raw) });","handlingStrategy":"validation","validationCode":"const m = /^\\d+$/.exec(raw ?? '');\nconst id = m && Number(m[0]) > 0 ? Number(m[0]) : undefined;\nif (id === undefined) throw new UserInputError('Expected a positive integer string');\nawait tool({ message_id: id });","typeGuard":"function isPositiveIntString(v: unknown): v is string {\n  return typeof v === 'string' && /^\\d+$/.test(v) && Number(v) > 0;\n}","tryCatchPattern":"try {\n  validatePositiveInt(value, 'cursor');\n} catch (err) {\n  if (err instanceof ValidationError) {\n    return badRequest(err.message); // surface to tool caller as 400\n  }\n  throw err;\n}","preventionTips":["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."],"tags":["mcp","validation","integer","string-parsing","parameters"],"backgroundTag":"invalid-parameter-type","analyzedSha":"749120085864ce16e0f273c7b86fac7740b39c5b","analyzedAt":"2026-08-17T21:21:45.363Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}