{"record":{"id":"08e082aa665991b2","repo":"vercel/ai","slug":"maxretries-must-be-0-08e082","errorCode":null,"errorMessage":"maxRetries must be >= 0","messagePattern":"maxRetries must be >= 0","errorType":"exception","errorClass":"MCPClientError","httpStatus":null,"severity":"error","filePath":"packages/mcp/src/tool/mcp-client.ts","lineNumber":151,"sourceCode":"  }\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) {\n    return maxTotalTimeout;\n  }\n\n  if (maxTotalTimeout == null) {\n    return timeout;\n  }","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/vercel/ai/blob/69428b1f8b037e4d118fb4853428d5c4e620493c/packages/mcp/src/tool/mcp-client.ts#L133-L169","documentation":"Thrown by prepareMaxRetries when maxRetries is a negative integer. Retrying a negative number of times is meaningless, so the constructor rejects it with MCPClientError.","triggerScenarios":"new MCPClient({ maxRetries: -1 }) or any negative integer, typically from miscomputed config (e.g. subtracting counts) or a sentinel value.","commonSituations":"Env-derived values like MAX_RETRIES=-1 used to mean 'disable retries'; arithmetic mistakes in derived config; misunderstanding that 0 is the correct way to disable retries.","solutions":["Use 0 to disable retries instead of a negative number.","Clamp with Math.max(0, value) before constructing the client.","Fix the source config/env value."],"exampleFix":"// before\nnew MCPClient({ ..., maxRetries: -1 });\n// after\nnew MCPClient({ ..., maxRetries: Math.max(0, Number(process.env.MCP_RETRIES ?? 2)) });","handlingStrategy":"validation","validationCode":"const maxRetries = Math.max(0, Number.parseInt(process.env.MCP_RETRIES ?? '2', 10));\nif (!Number.isInteger(maxRetries) || maxRetries < 0) {\n  throw new Error('maxRetries must be a non-negative integer');\n}","typeGuard":"function isNonNegativeInt(v: unknown): v is number {\n  return typeof v === 'number' && Number.isInteger(v) && v >= 0;\n}","tryCatchPattern":"try {\n  const client = await createMCPClient({ transport, maxRetries });\n} catch (e) {\n  if (MCPClientError.isInstance(e) && e.message === 'maxRetries must be >= 0') {\n    // clamp and retry construction\n  } else throw e;\n}","preventionTips":["Use 0 (not -1) to disable retries","Clamp config values with Math.max(0, value) at parse time","Document the expected range in config schemas (e.g. zod .int().min(0))"],"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"}