{"record":{"id":"cbd11ae050b4eaa4","repo":"vercel/ai","slug":"maxretries-must-be-an-integer-cbd11a","errorCode":null,"errorMessage":"maxRetries must be an integer","messagePattern":"maxRetries must be an integer","errorType":"exception","errorClass":"MCPClientError","httpStatus":null,"severity":"error","filePath":"packages/mcp/src/tool/mcp-client.ts","lineNumber":145,"sourceCode":"      statusCode >= 500\n    );\n  }\n\n  if (MCPClientError.isInstance(error) && error.code != null) {\n    return false;\n  }\n\n  const errorCode = getStringErrorCode(error);\n  return errorCode != null && DEFAULT_RETRY_ERROR_CODES.includes(errorCode);\n}\n\nfunction prepareMaxRetries(maxRetries: number | undefined): number {\n  if (maxRetries == null) {\n    return DEFAULT_MAX_TOOL_CALL_RETRIES;\n  }\n\n  if (!Number.isInteger(maxRetries)) {\n    throw new MCPClientError({\n      message: 'maxRetries must be an integer',\n    });\n  }\n\n  if (maxRetries < 0) {\n    throw new MCPClientError({\n      message: 'maxRetries must be >= 0',\n    });\n  }\n\n  return maxRetries;\n}\n\nfunction getEffectiveTimeout({\n  timeout,\n  maxTotalTimeout,\n}: RequestOptions): number | undefined {\n  if (timeout == null) {","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/vercel/ai/blob/69428b1f8b037e4d118fb4853428d5c4e620493c/packages/mcp/src/tool/mcp-client.ts#L127-L163","documentation":"Thrown by prepareMaxRetries (via MCPClientError) when a non-integer maxRetries value is passed to the MCPClient constructor. maxRetries controls how many times failed tool calls are retried and must be a whole number.","triggerScenarios":"Creating an MCP client with maxRetries set to a fractional number (e.g. 2.5), NaN, or Infinity instead of an integer (undefined/null is allowed and falls back to the default).","commonSituations":"Reading maxRetries from a config/env variable or CLI arg and forgetting to parse it with Number/parseInt; computing a fractional value like retries/2; passing NaN from an unparseable env string.","solutions":["Pass an integer: Math.floor/parseInt your value before constructing the client.","Validate config values at startup (Number.isInteger check).","Omit maxRetries entirely to use DEFAULT_MAX_TOOL_CALL_RETRIES."],"exampleFix":"// before\nnew MCPClient({ ..., maxRetries: Number(process.env.MCP_RETRIES) }); // NaN\n// after\nnew MCPClient({ ..., maxRetries: Number.parseInt(process.env.MCP_RETRIES ?? '2', 10) });","handlingStrategy":"validation","validationCode":"const maxRetries = Number(process.env.MCP_RETRIES);\nif (!Number.isInteger(maxRetries)) {\n  throw new Error('MCP_RETRIES must be an integer');\n}","typeGuard":"function isValidMaxRetries(v: unknown): v is number {\n  return typeof v === 'number' && Number.isInteger(v);\n}","tryCatchPattern":"try {\n  const client = await createMCPClient({ transport, maxRetries: rawRetries });\n} catch (e) {\n  if (MCPClientError.isInstance(e) && e.message === 'maxRetries must be an integer') {\n    // rebuild with default options\n  } else throw e;\n}","preventionTips":["Parse numeric env/config with Number.parseInt and validate with Number.isInteger","Centralize client config parsing in one validated factory","Omit maxRetries to accept the library default"],"tags":["mcp","configuration","validation","mcp-client"],"backgroundTag":"invalid-config-value","analyzedSha":"69428b1f8b037e4d118fb4853428d5c4e620493c","analyzedAt":"2026-08-30T12:32:21.016Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}