n8n-io/n8n · error · NodeOperationError

${uploadResponse.file.error?.message ?? 'Unknown error'}

Error message

${uploadResponse.file.error?.message ?? 'Unknown error'}

What it means

Final failure branch of uploadFile (buffer-based upload to /upload/v1beta/files). The code polls the File resource until state is ACTIVE or FAILED; on FAILED it throws the API's error.message, defaulting to 'Unknown error' when the error object is absent. Description: 'Error uploading file'.

Source

Thrown at packages/@n8n/nodes-langchain/nodes/vendors/GoogleGemini/helpers/utils.ts:110

		headers: {
			'Content-Length': numBytes,
			'X-Goog-Upload-Offset': '0',
			'X-Goog-Upload-Command': 'upload, finalize',
		},
		body: fileContent,
	})) as { file: File };

	while (uploadResponse.file.state !== 'ACTIVE' && uploadResponse.file.state !== 'FAILED') {
		await new Promise((resolve) => setTimeout(resolve, OPERATION_CHECK_INTERVAL));
		uploadResponse.file = (await apiRequest.call(
			this,
			'GET',
			`/v1beta/${uploadResponse.file.name}`,
		)) as File;
	}

	if (uploadResponse.file.state === 'FAILED') {
		throw new NodeOperationError(
			this.getNode(),
			uploadResponse.file.error?.message ?? 'Unknown error',
			{
				description: 'Error uploading file',
			},
		);
	}

	return { fileUri: uploadResponse.file.uri, mimeType: uploadResponse.file.mimeType };
}

async function getFileStreamFromUrlOrBinary(
	this: IExecuteFunctions,
	i: number,
	downloadUrl?: string,
	fallbackMimeType?: string,
	qs?: IDataObject,
): Promise<FileStreamData | FileBufferData> {

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Inspect the thrown message (response.error.message) — it usually names the rejected attribute (size/type).
  2. Re-encode or re-export the file to a supported MIME type (PDF, MP3, WAV, PNG/JPEG/WebP, MP4 per the Gemini docs).
  3. If transient, simply retry the upload (the node has no built-in retry here).
  4. Confirm the binary isn't empty — check the upstream node produced a non-zero-length file.
Defensive patterns

Strategy: retry

Validate before calling

function isUploadableFile(buf: Buffer, mimeType: string): boolean {
  const SUPPORTED = ['application/pdf','image/png','image/jpeg','image/webp','audio/mpeg','audio/wav','video/mp4'];
  return buf.length > 0 && SUPPORTED.includes(mimeType);
}

Type guard

interface GeminiFile { name: string; state: string; error?: { message: string } }
function isFileFailed(f: GeminiFile): boolean {
  return f.state === 'FAILED';
}

Try / catch

for (let attempt = 1; attempt <= 3; attempt++) {
  try { return await uploadFile(buf, mime); }
  catch (e) {
    if (attempt === 3 || /unsupported|too large/i.test(e.message)) throw e;
    await new Promise(r => setTimeout(r, 1000 * attempt));
  }
}

Prevention

When it happens

Trigger: Google's Files API accepted the bytes but the file ended in FAILED state: unsupported MIME type, file too large for the free tier, virus scan / safety rejection, malformed bytes, or a backend-side processing error.

Common situations: Uploading a format Gemini can't ingest (e.g. an obscure codec/container); a binary field that was empty or corrupted; transient Google backend failure during activation.

Related errors


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