The issue is that you’re creating a new FormData() object without passing the form to it, so the request body contains no form fields. As a result, the server receives an empty submission and sends blank emails.
You should build the FormData from the submitted form and handle the request properly:
form.addEventListener('submit', async (e) => {
e.preventDefault();
const data = new FormData(form); // or new FormData(e.target)
const response = await fetch('/subscribe', {
method: 'POST',
body: data,
});
if (!response.ok) {
console.error('Subscription failed');
}
});
Also verify that:
Your newsletter form inputs have name attributes (e.g. <input name="email">), otherwise FormData won’t include them.
The server reads the incoming form data correctly before generating the email.
You check the server response and display an error if the submission fails instead of silently ignoring it.
The main issue is that you’re creating a new FormData() object without passing in the form, so it’s empty. As a result, the request is sent successfully, but none of the form fields (such as the email address) are included.
I’d update it like this:
Create the FormData from the submitted form:
const data = new FormData(e.target);
or
const data = new FormData(form);
Handle the fetch() response so you can detect failures instead of silently ignoring them:
form.addEventListener('submit', async (e) => {
e.preventDefault();
const data = new FormData(e.target);
try {
const response = await fetch('/subscribe', {
method: 'POST',
body: data,
});
if (!response.ok) {
throw new Error('Subscription failed');
}
// Show a success message to the user.
} catch (err) {
// Display an error message and log the issue.
console.error(err);
}
});
If the backend is still receiving an empty email after this change, I’d also verify that:
The email input has a name attribute (e.g. name="email"), since FormData only includes named fields.
The server is reading multipart form data correctly.
The client waits for the request to complete and provides feedback if it fails.
The main issue is that you’re creating a new FormData() object without passing in the form, so it’s empty. As a result, the request is sent successfully, but none of the form fields (such as the email address) are included.
I’d update it like this:
Create the FormData from the submitted form:
const data = new FormData(e.target);
or
const data = new FormData(form);
Handle the fetch() response so you can detect failures instead of silently ignoring them:
form.addEventListener('submit', async (e) => {
e.preventDefault();
const data = new FormData(e.target);
try {
const response = await fetch('/subscribe', {
method: 'POST',
body: data,
});
if (!response.ok) {
throw new Error('Subscription failed');
}
// Show a success message to the user.
} catch (err) {
// Display an error message and log the issue.
console.error(err);
}
});
If the backend is still receiving an empty email after this change, I’d also verify that:
The email input has a name attribute (e.g. name="email"), since FormData only includes named fields.
The server is reading multipart form data correctly.
The client waits for the request to complete and provides feedback if it fails.
Spot the Bug answer: new FormData() is created empty instead of being constructed from the actual form element, so no field values are sent
The fix:
const data = new FormData(form); // pass the form (or e.target) into FormData
Why:
FormData() with no argument creates a blank form data object unrelated to the submitted form, so it never picks up the input values. Passing the form element (e.g. e.target or the form variable) makes FormData read its fields and include the email value in the request body.