n8n-io/n8n · warning · NodeOperationError

Video task did not complete within the maximum polling…

Error message

Video task ${taskId} did not complete within the maximum polling time. You can query the task manually using the task ID.

What it means

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.

Solutions

  1. Capture the taskId from the error context and re-query GET /query/video_generation?task_id=<id> manually until terminal.
  2. If pollVideoTask accepts a larger pollIntervalMs in your call path, raise it (note: total budget = attempts × interval).
  3. Wait a few minutes and resubmit a polling check for the same task rather than creating a new one.
  4. For routinely slow jobs, consider lowering resolution/duration so renders finish within the window.
Defensive patterns

Strategy: retry

Validate before calling

// The timeout is governed by MAX_POLL_ATTEMPTS (60) and pollIntervalMs (default 15000),
// i.e. ~15 min budget. If your call path lets you pass pollIntervalMs, size it so
// attempts * interval covers your worst-case render time.
function sizePollInterval(maxAttempts: number, expectedRenderMs: number): number {
  return Math.ceil(expectedRenderMs / maxAttempts);
}

Type guard

function isPollingTimeoutError(e: unknown): boolean {
  return e instanceof NodeOperationError && /did not complete within the maximum polling time/.test(e.message);
}

Try / catch

let result: { fileId: string; status: string };
try {
  result = await pollVideoTask.call(this, taskId);
} catch (error) {
  if (error instanceof NodeOperationError && /did not complete within the maximum polling time/.test(error.message)) {
    // Task is still running — keep the task_id and let the user re-query later.
    return [{ json: { taskId, status: 'still-running', message: 'Polling timed out; query the task manually.' } }];
  }
  throw error;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12). Data as JSON: /api/errors/745445fa9e94d5db. Report an issue: GitHub.

Appendix: source

Thrown at packages/@n8n/nodes-langchain/nodes/vendors/MiniMax/transport/index.ts:82

				const errorMessage = response?.base_resp?.status_msg || 'Video generation task failed';
				throw new NodeOperationError(this.getNode(), `Task failed: [${errorCode}] ${errorMessage}`);
			}

			const fileId = response?.file_id as string;
			if (!fileId) {
				throw new NodeOperationError(
					this.getNode(),
					'Video generation succeeded but no file_id was returned',
				);
			}

			return { fileId, status };
		}

		await sleep(pollIntervalMs);
	}

	throw new NodeOperationError(
		this.getNode(),
		`Video task ${taskId} did not complete within the maximum polling time. You can query the task manually using the task ID.`,
	);
}

export async function getVideoDownloadUrl(
	this: IExecuteFunctions,
	fileId: string,
): Promise<string> {
	const response = await apiRequest.call(this, 'GET', '/files/retrieve', {
		qs: { file_id: fileId },
	});

	const downloadUrl = response?.file?.download_url as string;
	if (!downloadUrl) {
		throw new NodeOperationError(
			this.getNode(),
			`Failed to retrieve download URL for file ${fileId}`,

View on GitHub (pinned to 5ac6606e81)