Skip to content

Commit f5b2ccb

Browse files
authored
chore(docs): add docs for handling batch trigger errors (#2838)
1 parent f73138f commit f5b2ccb

File tree

2 files changed

+86
-0
lines changed

2 files changed

+86
-0
lines changed

docs/limits.mdx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,10 @@ Batch triggering uses a token bucket algorithm to rate limit the number of runs
101101

102102
**How it works**: You can burst up to your bucket size, then tokens refill at the specified rate. For example, a Free user can trigger 1,200 runs immediately, then must wait for tokens to refill (100 runs become available every 10 seconds).
103103

104+
<Note>
105+
When you hit batch rate limits, the SDK throws a `BatchTriggerError` with `isRateLimited: true`. See [Handling batch trigger errors](/triggering#handling-batch-trigger-errors) for how to detect and react to rate limits in your code.
106+
</Note>
107+
104108
## Batch processing concurrency
105109

106110
The number of batches that can be processed concurrently per environment.

docs/triggering.mdx

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,6 +1100,88 @@ This works with all batch trigger methods:
11001100
Streaming is especially useful when generating batches from database queries, API pagination, or
11011101
file processing where you don't want to load all items into memory at once.
11021102

1103+
## Handling batch trigger errors
1104+
1105+
When batch triggering fails, the SDK throws a `BatchTriggerError` with properties that help you understand what went wrong and how to react:
1106+
1107+
| Property | Type | Description |
1108+
| :--- | :--- | :--- |
1109+
| `isRateLimited` | `boolean` | `true` if the error was caused by rate limiting |
1110+
| `retryAfterMs` | `number \| undefined` | Milliseconds until the rate limit resets |
1111+
| `phase` | `"create" \| "stream"` | Which phase of batch creation failed |
1112+
| `batchId` | `string \| undefined` | The batch ID if it was created before failure |
1113+
| `itemCount` | `number` | Number of items attempted in the batch |
1114+
| `cause` | `unknown` | The underlying error |
1115+
1116+
### Detecting and handling rate limits
1117+
1118+
When you hit [batch trigger rate limits](/limits#batch-trigger-rate-limits), you can detect this and implement retry logic:
1119+
1120+
```ts Your backend
1121+
import { tasks, BatchTriggerError } from "@trigger.dev/sdk";
1122+
import type { myTask } from "~/trigger/myTask";
1123+
1124+
async function triggerBatchWithRetry(items: { payload: { userId: string } }[], maxRetries = 3) {
1125+
for (let attempt = 0; attempt < maxRetries; attempt++) {
1126+
try {
1127+
return await tasks.batchTrigger<typeof myTask>("my-task", items);
1128+
} catch (error) {
1129+
if (error instanceof BatchTriggerError && error.isRateLimited) {
1130+
// Rate limited - wait and retry
1131+
const waitMs = error.retryAfterMs ?? 10000;
1132+
console.log(`Rate limited. Waiting ${waitMs}ms before retry ${attempt + 1}/${maxRetries}`);
1133+
await new Promise((resolve) => setTimeout(resolve, waitMs));
1134+
continue;
1135+
}
1136+
// Not a rate limit error - rethrow
1137+
throw error;
1138+
}
1139+
}
1140+
throw new Error("Max retries exceeded");
1141+
}
1142+
```
1143+
1144+
### Handling errors inside tasks
1145+
1146+
When calling `batchTrigger` from inside another task, you can handle errors similarly:
1147+
1148+
```ts /trigger/parent-task.ts
1149+
import { task, BatchTriggerError } from "@trigger.dev/sdk";
1150+
import { childTask } from "./child-task";
1151+
1152+
export const parentTask = task({
1153+
id: "parent-task",
1154+
run: async (payload: { userIds: string[] }) => {
1155+
const items = payload.userIds.map((userId) => ({ payload: { userId } }));
1156+
1157+
try {
1158+
const batchHandle = await childTask.batchTrigger(items);
1159+
return { batchId: batchHandle.batchId };
1160+
} catch (error) {
1161+
if (error instanceof BatchTriggerError) {
1162+
// Log details about the failure
1163+
console.error("Batch trigger failed", {
1164+
message: error.message,
1165+
phase: error.phase,
1166+
itemCount: error.itemCount,
1167+
isRateLimited: error.isRateLimited,
1168+
});
1169+
1170+
if (error.isRateLimited) {
1171+
// You might want to re-throw to let the task retry naturally
1172+
throw error;
1173+
}
1174+
}
1175+
throw error;
1176+
}
1177+
},
1178+
});
1179+
```
1180+
1181+
<Note>
1182+
For rate limit values and how the token bucket algorithm works, see [Batch trigger rate limits](/limits#batch-trigger-rate-limits).
1183+
</Note>
1184+
11031185
## Large Payloads
11041186

11051187
We recommend keeping your task payloads as small as possible. We currently have a hard limit on task payloads above 10MB.

0 commit comments

Comments
 (0)