vercel/ai · error · MCPClientError
maxRetries must be >= 0
Error message
maxRetries must be >= 0
What it means
Thrown by prepareMaxRetries when maxRetries is a negative integer. Retrying a negative number of times is meaningless, so the constructor rejects it with MCPClientError.
Source
Thrown at packages/mcp/src/tool/mcp-client.ts:151
}
const errorCode = getStringErrorCode(error);
return errorCode != null && DEFAULT_RETRY_ERROR_CODES.includes(errorCode);
}
function prepareMaxRetries(maxRetries: number | undefined): number {
if (maxRetries == null) {
return DEFAULT_MAX_TOOL_CALL_RETRIES;
}
if (!Number.isInteger(maxRetries)) {
throw new MCPClientError({
message: 'maxRetries must be an integer',
});
}
if (maxRetries < 0) {
throw new MCPClientError({
message: 'maxRetries must be >= 0',
});
}
return maxRetries;
}
function getEffectiveTimeout({
timeout,
maxTotalTimeout,
}: RequestOptions): number | undefined {
if (timeout == null) {
return maxTotalTimeout;
}
if (maxTotalTimeout == null) {
return timeout;
}View on GitHub (pinned to 69428b1f8b)
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.
Example fix
// before
new MCPClient({ ..., maxRetries: -1 });
// after
new MCPClient({ ..., maxRetries: Math.max(0, Number(process.env.MCP_RETRIES ?? 2)) }); Defensive patterns
Strategy: validation
Validate before calling
const maxRetries = Math.max(0, Number.parseInt(process.env.MCP_RETRIES ?? '2', 10));
if (!Number.isInteger(maxRetries) || maxRetries < 0) {
throw new Error('maxRetries must be a non-negative integer');
} Type guard
function isNonNegativeInt(v: unknown): v is number {
return typeof v === 'number' && Number.isInteger(v) && v >= 0;
} Try / catch
try {
const client = await createMCPClient({ transport, maxRetries });
} catch (e) {
if (MCPClientError.isInstance(e) && e.message === 'maxRetries must be >= 0') {
// clamp and retry construction
} else throw e;
} Prevention
- 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))
When it happens
Trigger: new MCPClient({ maxRetries: -1 }) or any negative integer, typically from miscomputed config (e.g. subtracting counts) or a sentinel value.
Common situations: 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.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- maxRetries must be an integer
- ACP MCP server ${JSON.stringify(name)} must be configured wi
- Pi MCP server ${JSON.stringify(name)} must be configured wit
- Invalid argument for parameter output: Invalid output type.
- Continuation maxAgeMs must be a positive integer.
AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30).
Data as JSON: /api/errors/08e082aa665991b2.
Report an issue: GitHub.