Documentation Index
Fetch the complete documentation index at: https://upstash.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
It is recommended to enable retries for workflow runs to improve reliability.
However, in some cases, you may want to stop execution immediately when an error occurs, without causing additional retries.
Upstash Workflow provides several mechanisms to terminate workflow execution gracefully.
Using WorkflowNonRetryableError
WorkflowNonRetryableError lets you explicitly fail a workflow without entering the retry cycle.
When thrown, the workflow run is marked as failed, which:
- Triggers the failure function (if defined)
- Sends the workflow run to the DLQ
export const { POST } = serve<{ topic: string }>(async (context) => {
const payload = context.requestPayload
const isExists = await context.run("is-user-exists", () => { ... });
if (!isExists) {
throw new WorkflowNonRetryableError("The user does not exists!")
}
})
Using context.cancel()
You can cancel a workflow run explicitly from inside the workflow.
When canceled, the run is labeled as canceled instead of failed. This means:
- The failure handler will NOT be triggered
- The workflow will NOT be sent to the DLQ
export const { POST } = serve<{ orderId: string }>(async (context) => {
const { orderId } = context.requestPayload;
// Check if order is still valid
const orderStatus = await context.run("check-order-status", async () => {
return await getOrderStatus(orderId);
});
if (orderStatus === "cancelled") {
// Stop execution gracefully without error
await context.cancel();
return;
}
// Continue processing if order is valid
await context.run("process-order", async () => {
return await processOrder(orderId);
});
});
Using conditional execution
You can also use guard conditions to skip certain steps and exit early, without throwing errors or canceling the workflow.
In this case, the workflow run completes successfully because no error was raised.
export const { POST } = serve<{ data: any }>(async (context) => {
const { data } = context.requestPayload;
// Check if order is still valid
const orderStatus = await context.run("check-order-status", async () => {
return await getOrderStatus(orderId);
});
if (orderStatus === "not-found") {
// Stop execution without error
return;
}
// Continue processing if order is valid
await context.run("process-order", async () => {
return await processOrder(orderId);
});
});