n8n-io/n8n · error · NodeOperationError

The file content is not in JSONL format

Error message

The file content is not in JSONL format

What it means

When uploading a fine-tuning file, the OpenAI API returns a 'Bad request' error with description 'Expected file to have JSONL format' if the file is not valid JSONL. The catch block detects this specific error pattern and rethrows as a NodeOperationError with a user-friendly description explaining that fine-tuning requires JSONL format where every line is a valid JSON dictionary. Other errors are rethrown unchanged.

Source

Thrown at packages/@n8n/nodes-langchain/nodes/vendors/OpenAi/v1/actions/file/upload.operation.ts:92

	try {
		const response = await apiRequest.call(this, 'POST', '/files', {
			option: { formData },
			headers: formData.getHeaders(),
		});

		return [
			{
				json: response,
				pairedItem: { item: i },
			},
		];
	} catch (error) {
		if (
			error.message.includes('Bad request') &&
			error.description?.includes('Expected file to have JSONL format')
		) {
			throw new NodeOperationError(this.getNode(), 'The file content is not in JSONL format', {
				description:
					'Fine-tuning accepts only files in JSONL format, where every line is a valid JSON dictionary',
			});
		}
		throw error;
	}
}

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Convert the file to JSONL format — one JSON object per line, no array wrapper, no trailing commas
  2. Validate each line parses as JSON before uploading (e.g. cat file.jsonl | jq -c . > /dev/null)
  3. Ensure the file extension and content type match — use .jsonl with application/jsonl or text/plain
  4. If using a binary file input, confirm the correct binary property name is selected

Example fix

// before — [{"text": "..."}, {"text": "..."}]\n (JSON array)
// after  — {"text": "..."}\n{"text": "..."}\n (JSONL, one object per line)
Defensive patterns

Strategy: validation

Validate before calling

// Validate JSONL format before uploading
function validateJsonl(content: string): boolean {
  const lines = content.trim().split('\n').filter(l => l.trim());
  return lines.every(line => {
    try { JSON.parse(line); return true; } catch { return false; }
  });
}
if (!validateJsonl(fileContent)) {
  throw new UserError('File is not valid JSONL. Each line must be a valid JSON object.');
}

Type guard

function isJsonlContent(content: string): boolean {
  if (!content.includes('\n')) return false;
  return content.trim().split('\n').every(line => {
    try { JSON.parse(line); return true; } catch { return false; }
  });
}

Try / catch

try {
  await uploadFile(this, i);
} catch (error) {
  if (error instanceof NodeOperationError && error.message.includes('JSONL')) {
    // Convert the file to JSONL and retry
    const converted = convertToJsonl(fileContent);
    await uploadJsonlString(this, i, converted);
  }
  throw error;
}

Prevention

When it happens

Trigger: A file uploaded with purpose 'fine-tune' is not in JSONL format. The OpenAI API validates the file server-side and returns a 400 with a description mentioning JSONL format. The catch block pattern-matches on error.message containing 'Bad request' and error.description containing 'Expected file to have JSONL format'.

Common situations: Uploading a .json array file instead of .jsonl; uploading a CSV or plain text file for fine-tuning; malformed JSONL with invalid JSON on some lines; wrong file selected in the node.

Related errors


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