Strange intermittent error with Put writing to KV from worker - fails randomly 80% of the time

Hello, I’m getting a very strange error while testing a simple worker that’s meant to process a one input email address form for a newsletter. The code below seems to work correctly only about 20% of the time. No exceptions or error messages come up - the Put command just fails silently and the rest of the code runs as expected, and if I view the KV entries only 1/5 make it in. There doesn’t seem to be any pattern with regard to the test email addresses that make it into the KV store. Very strange.

Code is below:

addEventListener(‘fetch’, event => {
event.respondWith(handleRequest(event.request))
})

async function handleRequest(request) {

if (request.method === ‘POST’) {
const body = await request.text();
const emailpost = body.split("=")[1];
const emailaddress = emailpost.replace("%40", “@”);
const timestamp = Date.now();

  try {
    EMAILS.put(timestamp, emailaddress);  

    //TESTING
    return new Response('POST! ' + '"' + emailaddress + '"', {
      headers: { 'content-type': 'text/plain' },
    });
  } catch (err) {
    return new Response(err.stack || err);
  }

} else {

  //TESTING
  return new Response('GET!', {
    headers: { 'content-type': 'text/plain' },
  });

}
}

If the request has been answered before PUT command has executed, the worker exits without completing PUT. Try to “await” the PUT command: “await EMAILS.put(timestamp, emailaddress);”

Like @lastguru said … you need to do await EMAILS.put(timestamp, emailaddress) or the Worker might return a response before completing the put request.

However… using await will block execution until the KV request has been processed… so it’s usually suggested to do the following (so you can add the KV asynchronously in the background):

  try {
    // DO NOT add an await in the next line
    event.waitUntil(EMAILS.put(timestamp, emailaddress));  

    //TESTING
    return new Response('POST! ' + '"' + emailaddress + '"', {
      headers: { 'content-type': 'text/plain' },
    });
  } catch (err) {
    return new Response(err.stack || err);
  }

Wrapping the put in a event.waitUntil will execute it in the background, allowing you to return the response immediately. The put will continue to run until it’s finished (even if the response has been returned) :slight_smile: