n8n-io/n8n · error · Error
--max-attempts must be >= 1
Error message
--max-attempts must be >= 1
What it means
Thrown by the build-mcp-manifest CLI after argument parsing. The --max-attempts flag controls how many total build attempts the builder makes per slug when a workflow ID is missing from the model's output. The check `result.maxAttempts < 1` rejects zero or negative values because zero attempts would mean no build work is done at all, making the entire run meaningless.
Source
Thrown at packages/@n8n/instance-ai/evaluations/cli/build-mcp-manifest.ts:232
result.suite = nextArg(argv, i, arg);
i += 2;
break;
case '-h':
case '--help':
return { helpRequested: true };
default:
if (arg.startsWith('--')) {
throw new Error(`Unknown flag: ${arg.split('=', 1)[0]} (use --help)`);
}
result.slugs.push(arg);
i += 1;
break;
}
}
if (result.iterations < 1) throw new Error('--iterations must be >= 1');
if (result.concurrency < 1) throw new Error('--concurrency must be >= 1');
if (result.maxAttempts < 1) throw new Error('--max-attempts must be >= 1');
if (result.source === 'langtracer' && !result.suite) {
throw new Error('--source langtracer requires --suite <slug>');
}
mkdirSync(result.outputDir, { recursive: true });
if (!result.manifestPath) result.manifestPath = join(result.outputDir, 'manifest.json');
if (!result.logDir) result.logDir = join(result.outputDir, 'logs');
const base = result.manifestPath.replace(/\.json$/, '');
result.statsPath = `${base}-stats.json`;
mkdirSync(result.logDir, { recursive: true });
return { helpRequested: false, args: result };
}
function readJson(path: string, label: string): unknown {
const content = readFileSync(path, 'utf-8');
try {
return JSON.parse(content);View on GitHub (pinned to 5ac6606e81)
Solutions
- Set --max-attempts to 1 or higher (the default is 3)
- Remove the flag entirely to use the default of 3
- If you want exactly one attempt with no retries, use --max-attempts 1
Example fix
# before pnpm eval:build-mcp-manifest --max-attempts 0 # after pnpm eval:build-mcp-manifest --max-attempts 1
Defensive patterns
Strategy: validation
Validate before calling
// Before invoking the CLI, validate numeric args in your wrapper script:
const rawMaxAttempts = process.env.MAX_ATTEMPTS ?? '3';
const maxAttempts = Number.parseInt(rawMaxAttempts, 10);
if (!Number.isInteger(maxAttempts) || maxAttempts < 1) {
throw new Error(`--max-attempts must be an integer >= 1, got: ${rawMaxAttempts}`);
} Type guard
function isValidAttemptCount(v: unknown): v is number {
return typeof v === 'number' && Number.isInteger(v) && v >= 1;
} Prevention
- Use the default (3) unless you have a specific reason to change maxAttempts
- Validate integer CLI args in wrapper scripts before passing them through
When it happens
Trigger: Running `pnpm eval:build-mcp-manifest --max-attempts 0` or `--max-attempts -1`. The value passes parseIntArg (0 and -1 are valid integers) but fails this post-parse range check at line 232.
Common situations: Developer sets --max-attempts to 0 thinking it means 'one attempt, no retries', not realizing the flag counts total attempts. A scripted/automated invocation passes 0 by default. A negative value from a misconfigured variable.
Related errors
- Missing value for ${flag}
- Invalid integer for ${flag}
- --source langtracer requires --suite <slug>
- Workflow directory not found: ${workflowDir}
- --build-cwd directory does not exist: ${args.buildCwd}
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/111d1eb5cfd6f6d1.
Report an issue: GitHub.