Describe the problem/error/question
I am developing a custom node for the Eulerian Technologies API. I need to upload a CSV file.
I am facing a strange issue where my custom node fails to upload the file, whereas the standard n8n HTTP Request node — configured with the exact same parameters — works perfectly (with binaries from CSV data).
The API returns an error stating it cannot find the file parameter, which suggests that the multipart/form-data body (or the boundary) is not being constructed correctly by this.helpers.request in my custom node, even though the configuration matches the working HTTP node.
What is the error message?
The API responds with a 200 OK (so auth and URL are correct) but returns this JSON error: {"error_msg": "externaldataupload_advertising | missing file-name parameter:", "error": true}
This implies the API cannot parse the specific form field named file-name.
HTTP Request node configuration (this works) :
- Method: Post
- URL: https://{customer}.api.eulerian.{datacenter}/ea/v2/ea/{site}/db/ope/externaldataupload_advertising.json
- Authentification: None
- Send Headers: true
- Specify Headers: Using Fields Below
- Name: Authorization
- Value : Bearer ${mytoken}
- Specify Headers: Using Fields Below
- Send Body: true
- Body Content Type: Form-Data
- Parameter Type: n8n Binary File
- Name: file-name
- Input Data Field Name: data
- Body Content Type: Form-Data
Request Options generated by HTTP Request node:
{“headers”:{“Authorization”:“Bearer ${mytoken}”,“accept”:“application/json,text/html,application/xhtml+xml,application/xml,text/;q=0.9, image/;q=0.8, /;q=0.7”},“method”:“POST”,“uri”:“https://{customer}.api.eulerian.{datacenter}/ea/v2/ea/{site}/db/ope/externaldataupload_advertising.json",“gzip”:true,“rejectUnauthorized”:true,“followRedirect”:false,“resolveWithFullResponse”:true,“timeout”:300000,“formData”:{“file-name”:{“value”:{“type”:“Buffer”,“data”:[101,97,58,100,97,116,101,59,101,97,58,111,112,101,59,101,97,58,108,111,99,97,116,105,111,110,59,101,97,58,99,114,101,97,116,105,118,101,59,101,97,58,101,120,116,101,114,110,97,108,95,118,105,101,119,59,101,97,58,101,120,116,101,114,110,97,108,95,99,108,105,99,107,59,101,97,58,101,120,116,101,114,110,97,108,95,99,111,115,116,10,50,48,49,52,45,48,49,45,48,49,59,67,97,109,112,97,105,103,110,95,110,97,109,101,95,49,59,76,111,99,97,116,105,111,110,95,49,59,67,114,101,97,116,105,118,101,95,49,59,49,50,51,52,53,59,48,59,48,10,50,48,49,52,45,48,49,45,48,49,59,67,97,109,112,97,105,103,110,95,110,97,109,101,95,49,59,76,111,99,97,116,105,111,110,95,49,59,67,114,101,97,116,105,118,101,95,49,59,49,50,51,59,50,59,48,10,50,48,49,52,45,48,49,45,48,49,59,67,97,109,112,97,105,103,110,95,110,97,109,101,95,50,59,76,111,99,97,116,105,111,110,95,49,59,67,114,101,97,116,105,118,101,95,49,59,49,54,53,59,50,49,59,48,46,50,51,10,50,48,49,52,45,48,49,45,48,50,59,67,97,109,112,97,105,103,110,95,110,97,109,101,95,49,59,76,111,99,97,116,105,111,110,95,49,59,67,114,101,97,116,105,118,101,95,49,59,53,59,48,59,48,46,49,50,10,50,48,49,52,45,48,49,45,48,51,59,67,97,109,112,97,105,103,110,95,110,97,109,101,95,49,59,76,111,99,97,116,105,111,110,95,49,59,67,114,101,97,116,105,118,101,95,49,59,53,48,48,59,49,50,59,49,53,46,50,10,50,48,49,52,45,48,49,45,48,52,59,67,97,109,112,97,105,103,110,95,110,97,109,101,95,49,59,76,111,99,97,116,105,111,110,95,49,59,67,114,101,97,116,105,118,101,95,49,59,48,59,50,59,49,46,50,10]},“options”:{“filename”:“data-to-upload-advertising.csv”,“contentType”:“text/csv”}}},“encoding”:null,“json”:false,"useStream”:true}
Request Response from HTTP Request node:
[{“error”: false,“data”: {“fields”: ,“rows”: },“meta”: {“reqid”: “14EDEA713F1E5E43CB308E2A4A1FAB8F”,“tm”: 1765492769,“host”: “er12”,“pid”: 22168,“total”: 0,“elapsed”: 345.192,“start”: 0}}]
The code from my custom node:
let requestConf: any = {
method: httpMethod,
url,
headers: {
'Content-Type': 'application/json'
}
};
if (!requestConf.headers) {
requestConf.headers = {};
}
if(edwSessionToken){
requestConf.headers['Authorization'] = `Bearer ${edwSessionToken}`;
}
else {
requestConf.headers['Authorization'] = `Bearer ${apiAuthentificationToken}`;
}
if (uploadOperations.includes(operation)) {
const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i);
const itemBinaryData = this.helpers.assertBinaryData(i, binaryPropertyName);
const uploadBuffer = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);
requestConf.formData = {
'file-name': {
value: uploadBuffer,
options: {
filename: itemBinaryData.fileName,
contentType: itemBinaryData.mimeType,
}
}
};
delete requestConf.headers['Content-Type'];
requestConf.headers['accept'] = 'application/json,text/html,application/xhtml+xml,application/xml,text/*;q=0.9, image/*;q=0.8, */*;q=0.7';
requestConf['gzip'] = true;
requestConf['rejectUnauthorized'] = true;
requestConf['followRedirect'] = false;
requestConf['resolveWithFullResponse'] = true;
requestConf['encoding'] = null;
requestConf['json'] = false;
requestConf['useStream'] = true;
requestConf['timeout'] = 300000;
} else {
if (!operation.includes('Delete') && ['DELETE', 'PATCH', 'POST', 'PUT'].includes(httpMethod)) {
requestConf.body = JSON.parse(requestBody);
}
}
console.log('url : ' + url);
console.log('requestConf : ' + JSON.stringify(requestConf));
const responseData = await this.helpers.httpRequest(requestConf);
console.log('responseData : ' + responseData);
if (typeof responseData === 'string') {
const trimmed = responseData.trim();
if (trimmed !== '') {
try {
returnData.push({ json: JSON.parse(trimmed) });
} catch {
returnData.push({ text: trimmed });
}
} else {
returnData.push({ 'Status Code': '204 No Content' });
}
} else if (responseData) {
returnData.push(responseData);
} else {
returnData.push({ 'Status Code': '204 No Content' });
}
Request Options generated by my custom node:
{"method":"POST","url":"https://{customer}.api.eulerian.{datacenter}/ea/v2/ea/{site}/db/ope/externaldataupload_advertising.json?file-name=data-to-upload-advertising.csv","headers":{"Authorization":"Bearer ${mytoken}","accept":"application/json,text/html,application/xhtml+xml,application/xml,text/*;q=0.9, image/*;q=0.8, */*;q=0.7"},"formData":{"file-name":{"value":{"type":"Buffer","data":[101,97,58,100,97,116,101,59,101,97,58,111,112,101,59,101,97,58,108,111,99,97,116,105,111,110,59,101,97,58,99,114,101,97,116,105,118,101,59,101,97,58,101,120,116,101,114,110,97,108,95,118,105,101,119,59,101,97,58,101,120,116,101,114,110,97,108,95,99,108,105,99,107,59,101,97,58,101,120,116,101,114,110,97,108,95,99,111,115,116,10,50,48,49,52,45,48,49,45,48,49,59,67,97,109,112,97,105,103,110,95,110,97,109,101,95,49,59,76,111,99,97,116,105,111,110,95,49,59,67,114,101,97,116,105,118,101,95,49,59,49,50,51,52,53,59,48,59,48,10,50,48,49,52,45,48,49,45,48,49,59,67,97,109,112,97,105,103,110,95,110,97,109,101,95,49,59,76,111,99,97,116,105,111,110,95,49,59,67,114,101,97,116,105,118,101,95,49,59,49,50,51,59,50,59,48,10,50,48,49,52,45,48,49,45,48,49,59,67,97,109,112,97,105,103,110,95,110,97,109,101,95,50,59,76,111,99,97,116,105,111,110,95,49,59,67,114,101,97,116,105,118,101,95,49,59,49,54,53,59,50,49,59,48,46,50,51,10,50,48,49,52,45,48,49,45,48,50,59,67,97,109,112,97,105,103,110,95,110,97,109,101,95,49,59,76,111,99,97,116,105,111,110,95,49,59,67,114,101,97,116,105,118,101,95,49,59,53,59,48,59,48,46,49,50,10,50,48,49,52,45,48,49,45,48,51,59,67,97,109,112,97,105,103,110,95,110,97,109,101,95,49,59,76,111,99,97,116,105,111,110,95,49,59,67,114,101,97,116,105,118,101,95,49,59,53,48,48,59,49,50,59,49,53,46,50,10,50,48,49,52,45,48,49,45,48,52,59,67,97,109,112,97,105,103,110,95,110,97,109,101,95,49,59,76,111,99,97,116,105,111,110,95,49,59,67,114,101,97,116,105,118,101,95,49,59,48,59,50,59,49,46,50,10]},"options":{"filename":"data-to-upload-advertising.csv","contentType":"text/csv"}}},"gzip":true,"rejectUnauthorized":true,"followRedirect":false,"resolveWithFullResponse":true,"encoding":null,"json":false,"useStream":true,"timeout":300000}
Request Response from my custom node:
[
{
"meta": {
"reqid": "5EBB111C7A306A695567E9782196CF02",
"tm": 1765493089,
"host": "er11",
"elapsed": 22.941,
"pid": 27008
},
"error_msg": "externaldataupload_advertising | missing file-name parameter: ",
"error": true
}
]
Thanks for reading!
Any help will be appreciate!

