webhook-response-not-sent

This error occurs when a webhook is configured with respondWith: "manual" but the workflow does not send a response using request.respondWith() before the webhook execution completes.


Error Message

Workflow run did not send a response

Why This Happens

When you create a webhook with respondWith: "manual", you are responsible for calling request.respondWith() to send the HTTP response back to the caller. If the workflow execution completes without sending a response, this error will be thrown.

The webhook infrastructure waits for a response to be sent, and if none is provided, it cannot complete the HTTP request properly.


Common Causes

Forgetting to Call request.respondWith()

// Error - no response sent
export async function webhookWorkflow() {
  "use workflow";

  const webhook = await createWebhook({
    respondWith: "manual",
  });

  const request = await webhook;
  const data = await request.json();

  // Process data...
  console.log(data);

  // Error: workflow ends without calling request.respondWith()
}

Solution: Always call request.respondWith() when using manual response mode.

// Fixed - response sent
export async function webhookWorkflow() {
  "use workflow";

  const webhook = await createWebhook({
    respondWith: "manual",
  });

  const request = await webhook;
  const data = await request.json();

  // Process data...
  console.log(data);

  // Send response before workflow ends
  await request.respondWith(new Response("Processed", { status: 200 })); 
}

Conditional Response Logic

// Error - response only sent in some branches
export async function webhookWorkflow() {
  "use workflow";

  const webhook = await createWebhook({
    respondWith: "manual",
  });

  const request = await webhook;
  const data = await request.json();

  if (data.isValid) {
    await request.respondWith(new Response("OK", { status: 200 }));
  }
  // Error: no response when data.isValid is false
}

Solution: Ensure all code paths send a response.

// Fixed - response sent in all branches
export async function webhookWorkflow() {
  "use workflow";

  const webhook = await createWebhook({
    respondWith: "manual",
  });

  const request = await webhook;
  const data = await request.json();

  if (data.isValid) { 
    await request.respondWith(new Response("OK", { status: 200 })); 
  } else { 
    await request.respondWith(new Response("Invalid data", { status: 400 })); 
  } 
}

Exception Before Response

// Error - exception thrown before response
export async function webhookWorkflow() {
  "use workflow";

  const webhook = await createWebhook({
    respondWith: "manual",
  });

  const request = await webhook;

  // Error occurs here
  throw new Error("Something went wrong"); 

  // Never reached
  await request.respondWith(new Response("OK", { status: 200 }));
}

Solution: Use try-catch to handle errors and send appropriate responses.

// Fixed - error handling with response
export async function webhookWorkflow() {
  "use workflow";

  const webhook = await createWebhook({
    respondWith: "manual",
  });

  const request = await webhook;

  try { 
    // Process request...
    const result = await processData(request); 
    await request.respondWith(new Response("OK", { status: 200 })); 
  } catch (error) { 
    // Send error response
    await request.respondWith( 
      new Response("Internal error", { status: 500 }) 
    ); 
  } 
}

Alternative: Use Default Response Mode

If you don't need custom response control, consider using the default response mode which automatically returns a 202 Accepted response:

// Automatic 202 response - no manual response needed
export async function webhookWorkflow() {
  "use workflow";

  const webhook = await createWebhook(); 
  const request = await webhook;

  // Process request asynchronously
  await processData(request);

  // No need to call request.respondWith()
}

Learn More