{"record":{"id":"745445fa9e94d5db","repo":"n8n-io/n8n","slug":"video-task-taskid-did-not-complete-within-the-m","errorCode":null,"errorMessage":"Video task ${taskId} did not complete within the maximum polling time. You can query the task manually using the task ID.","messagePattern":"Video task (.+?) did not complete within the maximum polling time\\. You can query the task manually using the task ID\\.","errorType":"exception","errorClass":"NodeOperationError","httpStatus":null,"severity":"warning","filePath":"packages/@n8n/nodes-langchain/nodes/vendors/MiniMax/transport/index.ts","lineNumber":82,"sourceCode":"\t\t\t\tconst errorMessage = response?.base_resp?.status_msg || 'Video generation task failed';\n\t\t\t\tthrow new NodeOperationError(this.getNode(), `Task failed: [${errorCode}] ${errorMessage}`);\n\t\t\t}\n\n\t\t\tconst fileId = response?.file_id as string;\n\t\t\tif (!fileId) {\n\t\t\t\tthrow new NodeOperationError(\n\t\t\t\t\tthis.getNode(),\n\t\t\t\t\t'Video generation succeeded but no file_id was returned',\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn { fileId, status };\n\t\t}\n\n\t\tawait sleep(pollIntervalMs);\n\t}\n\n\tthrow new NodeOperationError(\n\t\tthis.getNode(),\n\t\t`Video task ${taskId} did not complete within the maximum polling time. You can query the task manually using the task ID.`,\n\t);\n}\n\nexport async function getVideoDownloadUrl(\n\tthis: IExecuteFunctions,\n\tfileId: string,\n): Promise<string> {\n\tconst response = await apiRequest.call(this, 'GET', '/files/retrieve', {\n\t\tqs: { file_id: fileId },\n\t});\n\n\tconst downloadUrl = response?.file?.download_url as string;\n\tif (!downloadUrl) {\n\t\tthrow new NodeOperationError(\n\t\t\tthis.getNode(),\n\t\t\t`Failed to retrieve download URL for file ${fileId}`,","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/nodes-langchain/nodes/vendors/MiniMax/transport/index.ts#L64-L100","documentation":"Thrown by pollVideoTask when the loop exceeds MAX_POLL_ATTEMPTS (60) without hitting a terminal status. With DEFAULT_POLL_INTERVAL_MS of 15000, this caps total polling at roughly 15 minutes. The error is recoverable: the task is not necessarily failed, just not yet terminal, and the user is told they can query it manually via the task ID.","triggerScenarios":"Video rendering genuinely takes longer than 15 minutes (long/high-resolution videos); MiniMax backend under heavy load queuing the job; a custom pollIntervalMs was passed that, combined with MAX_POLL_ATTEMPTS=60, shortens the window; the job is stuck in a non-terminal status indefinitely.","commonSituations":"High-resolution or long-duration videos on a loaded backend; a caller passing a small pollIntervalMs which reduces total wall-clock budget; account in a slow queue tier; transient MiniMax slowness.","solutions":["Capture the taskId from the error context and re-query GET /query/video_generation?task_id=<id> manually until terminal.","If pollVideoTask accepts a larger pollIntervalMs in your call path, raise it (note: total budget = attempts × interval).","Wait a few minutes and resubmit a polling check for the same task rather than creating a new one.","For routinely slow jobs, consider lowering resolution/duration so renders finish within the window."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// The timeout is governed by MAX_POLL_ATTEMPTS (60) and pollIntervalMs (default 15000),\n// i.e. ~15 min budget. If your call path lets you pass pollIntervalMs, size it so\n// attempts * interval covers your worst-case render time.\nfunction sizePollInterval(maxAttempts: number, expectedRenderMs: number): number {\n  return Math.ceil(expectedRenderMs / maxAttempts);\n}","typeGuard":"function isPollingTimeoutError(e: unknown): boolean {\n  return e instanceof NodeOperationError && /did not complete within the maximum polling time/.test(e.message);\n}","tryCatchPattern":"let result: { fileId: string; status: string };\ntry {\n  result = await pollVideoTask.call(this, taskId);\n} catch (error) {\n  if (error instanceof NodeOperationError && /did not complete within the maximum polling time/.test(error.message)) {\n    // Task is still running — keep the task_id and let the user re-query later.\n    return [{ json: { taskId, status: 'still-running', message: 'Polling timed out; query the task manually.' } }];\n  }\n  throw error;\n}","preventionTips":["Treat the polling timeout as recoverable: persist the task_id and re-query later instead of failing the workflow.","If your integration lets you pass pollIntervalMs, size attempts × interval to cover realistic render times for high-resolution video.","Lower resolution/duration for routinely slow jobs so renders finish inside the window.","Surface the task_id in the error output so the user can resume manually."],"tags":["minimax","video-generation","polling","timeout","long-running"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}