eyaltoledano/claude-task-master · error · TypeError
Invalid maxAttempts value: ${maxAttempts}. Must be a positiv
Error message
Invalid maxAttempts value: ${maxAttempts}. Must be a positive integer. What it means
A synchronous TypeError guard in verifyMFAWithRetry. The method retries MFA verification a bounded number of times, so maxAttempts must be a finite positive integer (>= 1). Values like 0, -1, NaN, Infinity, or non-integers are rejected before any verification attempt is made.
Source
Thrown at packages/tm-core/src/modules/auth/managers/auth-manager.ts:174
*/
async verifyMFAWithRetry(
factorId: string,
codeProvider: () => Promise<string>,
options?: {
maxAttempts?: number;
onInvalidCode?: (attempt: number, remaining: number) => void;
}
): Promise<MFAVerificationResult> {
const maxAttempts = options?.maxAttempts ?? 3;
const onInvalidCode = options?.onInvalidCode;
// Guard against invalid maxAttempts values
if (
!Number.isFinite(maxAttempts) ||
!Number.isInteger(maxAttempts) ||
maxAttempts < 1
) {
throw new TypeError(
`Invalid maxAttempts value: ${maxAttempts}. Must be a positive integer.`
);
}
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
try {
const code = await codeProvider();
const credentials = await this.verifyMFA(factorId, code);
return {
success: true,
attemptsUsed: attempt,
credentials
};
} catch (error) {
// Only retry on invalid MFA code errors
if (
error instanceof AuthenticationError &&
error.code === 'INVALID_MFA_CODE'View on GitHub (pinned to c0c98d367c)
Solutions
- Pass a positive integer, e.g. Math.max(1, Math.floor(Number(maxAttempts)))
- Validate user/config input before calling: Number.isInteger(n) && n >= 1
- If 0 was intended as 'single attempt, no retries', pass 1 instead
Example fix
// before
await auth.verifyMFAWithRetry(code, factorId, Number(opts.retries)); // NaN if flag missing
// after
const retries = Number(opts.retries ?? 1);
if (!Number.isInteger(retries) || retries < 1) throw new Error('retries must be a positive integer');
await auth.verifyMFAWithRetry(code, factorId, retries); Defensive patterns
Strategy: validation
Validate before calling
function isValidMaxAttempts(n: unknown): n is number {
return typeof n === 'number' && Number.isFinite(n) && Number.isInteger(n) && n >= 1;
}
if (!isValidMaxAttempts(maxAttempts)) maxAttempts = 1; Type guard
function isPositiveInt(v: unknown): v is number {
return typeof v === 'number' && Number.isInteger(v) && v >= 1;
} Try / catch
try {
await auth.verifyMFAWithRetry(code, factorId, maxAttempts);
} catch (e) {
if (e instanceof TypeError && e.message.includes('maxAttempts')) {
// programmer error: clamp and retry once with a valid value
await auth.verifyMFAWithRetry(code, factorId, 3);
} else throw e;
} Prevention
- Always coerce and validate numeric CLI/config input before passing it
- Use Math.floor + range checks when deriving attempts from user input
- Never pass 0 to mean 'single attempt' — the minimum valid value is 1
- Write unit tests covering NaN, 0, negatives, and fractional inputs
When it happens
Trigger: Calling authManager.verifyMFAWithRetry(code, factorId, maxAttempts) with maxAttempts = 0, a negative number, NaN, Infinity, or a fractional value like 1.5 — typically from unvalidated CLI input or a bad config value.
Common situations: CLI parsing that yields NaN when a flag is omitted; config files where attempts is a string like '3'; off-by-one logic passing 0 to mean 'no retries' (author intent) but failing validation.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Invalid subtask ID format: ${subtaskId}. Expected format: "p
- Payload must be an object
- Provider name must be a non-empty string
- Provider instance is required
- No text stream provided
AI-assisted analysis of eyaltoledano/claude-task-master@c0c98d367c (2026-08-29).
Data as JSON: /api/errors/00606bd520993923.
Report an issue: GitHub.