Skip to main content

Overview

OpenAI API calls can be slow or occasionally fail. This task configures custom retry options at the task level (overriding the project defaults) and explicitly throws an error when OpenAI returns an empty response — which triggers a retry without needing any extra tooling.

Task code

trigger/openai.ts
import { task } from "@trigger.dev/sdk";
import OpenAI from "openai";

const openai = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
});

export const openaiTask = task({
  id: "openai-task",
  // These retry options override the defaults defined in your trigger.config.ts
  retry: {
    maxAttempts: 10,
    factor: 1.8,
    minTimeoutInMs: 500,
    maxTimeoutInMs: 30_000,
    randomize: false,
  },
  run: async (payload: { prompt: string }) => {
    // If this call throws, the task will be retried automatically
    const chatCompletion = await openai.chat.completions.create({
      messages: [{ role: "user", content: payload.prompt }],
      model: "gpt-3.5-turbo",
    });

    if (chatCompletion.choices[0]?.message.content === undefined) {
      // OpenAI occasionally returns an empty response.
      // Throwing here triggers a retry of the whole task.
      throw new Error("OpenAI returned an empty response");
    }

    return chatCompletion.choices[0].message.content;
  },
});

How retrying works

The retry config on the task controls how Trigger.dev retries the entire run if it throws:
OptionValueDescription
maxAttempts10Maximum total attempts (1 initial + 9 retries)
factor1.8Exponential back-off multiplier
minTimeoutInMs500Wait at least 500ms before the first retry
maxTimeoutInMs30_000Cap retries at 30 seconds apart
randomizefalseDon’t add jitter to the back-off timing
If you only want to retry a specific part of your task (for example, one API call among many), use retry.onThrow to wrap just that block. See the Resend email sequence example for a pattern using retry.onThrow.

Testing your task

To test this task in the Trigger.dev dashboard, use the following payload on the Test page:
{
  "prompt": "What is the meaning of life?"
}

Resend email sequence

Use retry.onThrow for partial retries within a multi-step task

FFmpeg video processing

Process video files using FFmpeg in a background task

Build docs developers (and LLMs) love