{"record":{"id":"f5fb50bccd753258","repo":"vercel/ai","slug":"invalid-n-expected-a-positive-integer-received","errorCode":null,"errorMessage":"Invalid n: expected a positive integer, received ${JSON.stringify(n)}.","messagePattern":"Invalid n: expected a positive integer, received (.+?)\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/ai/src/generate-video/start-video.ts","lineNumber":142,"sourceCode":"  >;\n  generateAudio?: boolean;\n  providerOptions?: ProviderOptions;\n  maxRetries?: number;\n  abortSignal?: AbortSignal;\n  headers?: Record<string, string>;\n  webhookUrl?: string;\n}): Promise<StartVideoResult> {\n  const model = resolveVideoModel(modelArg);\n\n  if (model.doStart == null) {\n    throw new Error(\n      `Video model ${model.modelId} does not implement doStart. ` +\n        'Use generateVideo for models without an asynchronous start/status flow.',\n    );\n  }\n\n  if (!Number.isInteger(n) || n < 1) {\n    throw new Error(\n      `Invalid n: expected a positive integer, received ${JSON.stringify(n)}.`,\n    );\n  }\n\n  // A start yields one operation covering all n videos: refuse to silently\n  // exceed a known per-call limit instead of splitting into several starts.\n  const knownMaxVideosPerCall =\n    maxVideosPerCall ??\n    (typeof model.maxVideosPerCall === 'function'\n      ? await model.maxVideosPerCall({ modelId: model.modelId })\n      : model.maxVideosPerCall);\n  if (knownMaxVideosPerCall != null && n > knownMaxVideosPerCall) {\n    throw new Error(\n      `Video model ${model.modelId} supports at most ${knownMaxVideosPerCall} video(s) per call, ` +\n        `but ${n} were requested. Split the batch across multiple startVideo calls.`,\n    );\n  }\n","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/vercel/ai/blob/69428b1f8b037e4d118fb4853428d5c4e620493c/packages/ai/src/generate-video/start-video.ts#L124-L160","documentation":"startVideo validates that n is a positive integer before starting the job. Anything else (0, negative, fractional, NaN, non-number) throws this validation Error with the JSON of the received value. This guards against building an invalid provider request.","triggerScenarios":"experimental_startVideo called with n = 0, negative n, non-integer values like 1.5, NaN, or a string/undefined n.","commonSituations":"n computed from dynamic input (user-supplied count, array length of empty list, parseFloat output); default value not applied so n is undefined.","solutions":["Pass a positive integer for n (>= 1).","Clamp/round computed values: Math.max(1, Math.round(x)).","Validate input before calling startVideo.","Default undefined n explicitly to 1."],"exampleFix":"// before\nconst n = Number(userInput); // could be NaN/0/1.5\nawait experimental_startVideo({ model, prompt, n });\n// after\nconst n = Math.max(1, Math.round(Number(userInput) || 1));\nawait experimental_startVideo({ model, prompt, n });","handlingStrategy":"validation","validationCode":"function assertValidN(n) {\n  if (!Number.isInteger(n) || n < 1) throw new Error(`Invalid n: ${JSON.stringify(n)}`);\n}\nassertValidN(n);","typeGuard":"function isValidN(n) {\n  return typeof n === 'number' && Number.isInteger(n) && n >= 1;\n}","tryCatchPattern":"try {\n  await experimental_startVideo({ model, prompt, n });\n} catch (e) {\n  if (e.message.startsWith('Invalid n')) {\n    // coerce/fix n and retry\n    await experimental_startVideo({ model, prompt, n: 1 });\n  }\n}","preventionTips":["Always coerce user-supplied counts with Number.isInteger checks.","Default n explicitly (e.g. n ?? 1).","Avoid parseFloat for counts; use parseInt/Math.round.","Validate batch inputs at the UI boundary."],"tags":["video","validation","arguments"],"backgroundTag":"invalid-argument","analyzedSha":"69428b1f8b037e4d118fb4853428d5c4e620493c","analyzedAt":"2026-08-30T12:32:21.016Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}